Uusi palstan käyttäjä tässä moi.
Tällainen ongelma josta ei millään meinaa päästä eroon.
VB6:lla tehdystä exestä tulostetaan erillisiin Crystal Reportsilla (versio 9) tehtyihin .rpt tiedostoihin.
Satunnaisesti (ja aika usein) heittää tulostettaessa ohjelmasta pihalle. Ei sen kummempaa virheilmoitustakaan, kuin vain että ohjelma lakkasi toimimasta.
Sellainen huomio että kun exen avaa ja menee eka kerran tulostamaan jostain formista, niin tulostus onnistuu ok. Ohjelman ollessa auki ja tulostettaessa samaan pohjaan muutaman minsan päästä, heittää pihalle satavarmasti.
Olen laitellut koodiin kyllä ns. tappamiset tyyliin Set report=Nothing jne.
Onko muilla vastaavia ongelmia ja mikä neuvoksi?
Alla koodia, kippaa tuon Report.Database.SetDataSource -rivin kohdalla.
adoPrintData on recordsettiin avattu tietue, ja se on kyllä tuossa kohtaa aina auki ja on tietueita.
Dim crystal As New CRAXDRT.Application Set crystal = Nothing Dim Report As New CRAXDRT.Report Set Report = Nothing Set crystal = New CRAXDRT.Application Set Report = crystal.OpenReport("c:\tulostepohjat\pohja1.rpt", 1) Report.DiscardSavedData Report.Database.SetDataSource adoPrintData, 3 Report.PrintOut True, 1 Set Report = Nothing Set crystal = Nothing
Mod. lisäsi kooditagit!
Oletko yrittänyt ottaa mahdollista virhettä try catchillä kiinni?
groovyb kirjoitti:
(10.12.2015 20:12:39): Oletko yrittänyt ottaa mahdollista virhettä try...
En. Mitenkäs tuollainen onnistuu?
Oletko mielestäsi käyttänyt New-komentoja fiksusti? En toki VB6:lla koodaa, mutta tuo näyttää aika oudolta, ja netissä kerrotaan, että juuri VB6:n kohdalla koodi toimii vielä kummallisemmin kuin samanlaiset rivit muissa kielissä. Kokeilepa muuttaa koodi tällaiseksi:
Dim crystal As CRAXDRT.Application Dim report As CRAXDRT.Report Set crystal = New CRAXDRT.Application Set report = crystal.OpenReport("c:\tulostepohjat\pohja1.rpt", 1) report.DiscardSavedData report.Database.SetDataSource adoPrintData, 3 report.PrintOut True, 1 Set report = Nothing Set crystal = Nothing
En tiedä, korjaako tämä kokemaasi virhettä, mutta ainakin koodi on selvempi.
Edit: Korjasin linkin.
groovyb kirjoitti:
Oletko yrittänyt ottaa mahdollista virhettä try catchillä kiinni?
Onkohan VB6:ssa sellaisia?
Metabolixin koodi on kylläkin täysijärkisempää kuin timotaikurin alkuperäinen koodi, mutta näyttäisi käytännössä tekevän täsmälleen saman. (Ainakin jos niitä käyttävä koodi on kokonaisuudessaan tuossa). Että sikäli muuttaminen tuskin korjaa varsinaista ongelmaa.
Vaikka koodista voisi kuvitella, niin 1. ja 3. rivi eivät luo objekteja eivätkä 2. ja 4. rivit poista niitä. (Koska VB6:n ...As New... tyyppinen määrittely tarkoittaa että objekti luodaan silloin, kun objektimuuttujaa joka on Nothing käytetään. Asettaminen ei ole käyttöä.
VB6:ssa ei tosiaan ole Try Catch -mallia, mutta tokihan siellä voi tehdä
On Error Goto Virheenkäsittelijä '..Koodia Exit Sub 'tms / Poistutaan ennen virheenkäsittelijää Virheenkäsittelijä: 'Err -objektissa on tietoa virheestä
Muutin koodin Metabolixin mukaiseksi. Kokeilin tulostusta 10 x peräjälkeen,välillä parin minuutin tako, ei kaatunut kertaakaan, eli varovaisen toiveikas. Huomenna testiä isommalla massalla, näkee sitten korjautuiko.
Grez: Toki virheenkäsittelijä on päällä (MsgBox Err.Description, jne) mutta eipä se ole mitään auttanut koska viskaa ohjelmasta ulos kertomatta mitään syytä.
Eipä tuo Metabolixin koodi auttanut ongelmaan. Sellainen huomio että kun tulostaa peräjälkeen toistuvasti useita kertoja, niin ei kippaa ulos.
Kun pitää tulostamisen välillä vähintään 2 min tauon (exe auki koko ajan), niin kippaa varmasti ulos.
Olisinkin ollut yllättynyt, jos olisi auttanut, kun mitään todellista muutosta ei tapahtunut.
Jos systeemi ei ole hirveän laaja, niin tekisin sen uusiksi VB.Netillä (tai no oikeastaan C#:lla). Tuo VB6:n kanssa tappelu käy äkkiä turhauttavaksi.
Systeemi on iso, kynnys tehdä projekti uudelleen c# on suht iso, eikä asiakasta saa tätä millään maksamaan.
C# on kyllä hankittu ja koneella mutta pari kertaa sitä kokeiltua tuntuu
työläältä kalulta, yksinkertainen comboboxiin datan lataaminenkin vaikutti monimutkaisemmalta kuin vb6:ssa.
En vielä luovuta, koska tiedän että laajasti asiakkailla käytössä olevia, vb6/crystal kaluilla tehtyjä ohjelmia pelittää 100% ...
Täytyisköhän laittaa kyssäriä tuonne crystalin tukeen, lienee nykyisin sapin omistuksessa.
Jos systeemi on iso, miten olet liittänyt kaatumisen tulostamiseen, jos itse tulostaminen ei edes kaada sovellusta?
Tulostaminen rpt:hen juurikin on se mikä kaataa sovelluksen. Muuten systeemi pyörii ongelmattomasti, grideihin lataaminen, tietokantapäivitykset jne.
Tuossa ei kuitenkaan ole ilmeisesti koko koodi, eli et voi varmaksi tietää että vika on juuri tuossa? Ainakin adoPrintData taitaa olla jossain muualla määritelty.
adoPrintData (recordset) avataan ennen noita rivejä näin:
Dim adoPrintData As ADODB.Recordset Set adoPrintData= CreateObject("ADODB.Recordset") adoPrintData.CursorLocation = adUseClient Dim mSQL as string mSQL="SELECT fiel1,field2 FROM taulu1 WHERE field1=1" adoPrintData.Open mSQL, gAdocnnClient, adOpenKeyset, adLockOptimistic, adCmdText
(Tuo gAdocnnClient on projektin loginissa avattu tietokantayhteys)
Muuta koodia ei ole tulostamisessa.
Olen laitellut rivien väleihin Msgboxeja jotta saan selville missä kohtaa kilahtaa ulos ja se on nimenomaan tuon SetDataSource-rivin kohdalla.
Mod. lisäsi kooditagit!
Menisikö toi gAdocnnClient sitten jotenkin jumiin tai epämääräiseen tilaan, joka aiheuttaisi kaatumisen.
Testasin tuonkin laittamalla tuohon koodia joka sulkee gAdoCnnClientin ennen SetDataSource riviä yhteyden ja avaa sen uudelleen.
Muutaman kerran tulosti ok jonka jälkeen taas ohjelmasta pihalle.
Ongelma liittynee crystalin johonkin bugiin tms, rpt ei osaa ottaa toistuvasti 100% varmuudella clientista dataa vastaan. Tämä on minun olettamukseni.
Kaatumista ei tapahtuisi jos vb.exen sulkisi joka kerta ennen tulostusta ja avaisi uudelleen samaan tilanteeseen missä oltiin, mutta sellaisen koodaaminen on aika haastava homma.
Yleisesti ottaen tuollaisten ongelmien jossa koko ohjelma vaan katoaa ilman virheenkäsittelyyn menemistä on haastavaa. Jos en saisi ongelmaa mitenkään muuten korjattua niin saattaisin jopa tehdä tuon yhden ongelmaosion jollain muulla kielellä ja kutsua sitä erillistä modulia VB:stä. Kun siis kerran koko systeemiä ei pysty kerralla päivittämään nykyaikaan.
voiko olla mahdollista, että .rpt tiedosto on lukitussa tilassa?
Seuraavanlaisen pätkän löysin ko. tarkistuksesta:
' Return True if the file is locked to prevent the desired ' access. Private Function FileIsLocked(ByVal filename As String, _ Optional ByVal for_write As Boolean = True) As Boolean Const PERMISSION_DENIED As Integer = 70 Dim fnum As Integer Dim err_number As Integer On Error Resume Next fnum = FreeFile If for_write Then Open filename For Append As #fnum err_number = Err.Number Else Open filename For Input As #fnum err_number = Err.Number End If Close #fnum On Error GoTo 0 If err_number = 0 Then FileIsLocked = False ElseIf err_number = PERMISSION_DENIED Then FileIsLocked = True Else Err.Raise err_number End If End Function
Laitoin tuon FileIsLocked funktion projektiini ja tarkistuttamaan josko .rpt on jäänyt lukituksi ennen riviä ...SetDataSource..
Tein Timerin joka pyörittää 5 sekunnin välein tuota mun koodia (disabloin Report.PrintOut -rivin ettei tulosta turhaan)
Sellaiset 10-15 kertaa pyörittää ok ennenkuin heittää softasta pihalle ennen SetDataSource-riviä, kertomatta mitään vihjaavaa syytä.
Kyllähän tämä alkaa vaikuttamaan yhä selvemmin crystalin ongelmalta, tai sitten joku olennainen koodinpätkä tuosta minulta puuttuu.
Eikös se tarkistus pidä olla ennen crystal.OpenReport kutsua, siinähän tuo filu napataan?
Siirsin tarkistusfunktion tuon crystal.OpenReport rivin yläpuolelle.
Ei antanut kertaakaan tietoa että .rpt olisi lukittuna, eikä näin auttanut ongelmaan. Ohjelma kippaa tuosta SetDataSource -rivistä.
Seuraavaksi voisit kokeilla tarkastaa tietokantayhteyden tilan ennen käyttöä, ja sallia haun vain kun tila == 1 (Open). Mahdollisesti voisit myös sulkea yhteyden käytön jälkeen, ja avata yhteyden uudelleen kun kantaa seuraavaa kerran tarvitaan.
Tavallaan tietokantayhteys on tullut jo aikaisemmin testattua tuolla jossa keskusteltiin gAdoCnnClientistä.
Laitoin nyt ennen SetDatasourcea uuden rivin MsgBox gAdoCnnClient.State ja antaa
aina arvon 1, myös siinä kohtaa luupissa jossa heittää taas pihalle.
Laitoin myös ehdon jos State<>1 niin hypätään SetDataSourcen yli, sama lopputulos.
Kantaan siis yhteys toimii, mutta ei pukkaa rpt:hen dataa toistuvasti ilman kaatumista.
Voisin testata seuraavaksi niin että kopioin samalla rpt-pohjalla
20 erinimisiä rpt-tiedostoja ja kutsun niitä luupissa joka kerta eri nimistä pohjaa. Luuppaus niin kauan kuin on erinimisiä rpt-pohjia.
Saas nähä loppuuko ensin luuppi ennen kippaamista.
Tosta ADODB.Connectionin tilan tarkistamisesta ei muuten yleisesti ottaen ole mitään hyötyä. Se antaa 1 vaikka yhteys olisikin katkennut, ellei sitä ole katkaistu ohjelman päästä (Close -komennolla). Sen lukeminen ei siis testaa yhteyden toimivuutta, vaan kertoo vaan mihin tilaan yhteys on ohjelman puolelta jäänyt.
Mutta tosiaan tuskin vika siinä on, kun kerran jo kokeilit avata yhteyden uudelleen.
Kopioin identtisiä rpt-pohjia 30 kpl, ja nimesin kunkin filun eri nimellä rtp1,rpt2 jne.
Luuppaus 30x kussakin luupissa eriin rpt, exen sammutus välillä ja taas luuppaus ja tulostus. Sama yht. 5 kertaa -> ei kertaakaan pihalle ohjelmasta.
Mutta pihalle mennään satunnaisesti jos exea ei välillä sulje.
Eli johtopäätös on että ohjelma kaatuu satunnaisesti kun tulostetaan saman exe-session aikana samannimiseen rpt-pohjaan useammin kuin yhden kerran.
Seuraava kysymys onkin miten tuo kaatuminen estetään ilman että tarvii exea sammuttaa välillä. Jollain tapaa rpt-tiedostot pitäisi "nollata" jokaisen tulostuksen jälkeen?
Testaukset jatkuneet. Tulostaa kylläkin samaan tiedostonimeen useaan kertaan yhden exe-istunnon aikana mutta näyttää siltä että kun pitää taukoa tulostamisessa esim vähintään minuutin niin sen jälkeen heittää ulos ekalla yrittämällä tauon jälkeen.
Kun tulostaa peräjälkeen vaikka 10 sek tauolla 50 x putkeenkin niin toimii ok.
Onpa mystinen ongelma.
Yhteys kantaan on kyllä koko ajan auki, se on testattu sulkemalla ja avaamalla yhteys aina ennen tulostusta.
Pystytkö purkkaratkaisuna tulostamaan säännöllisin välein tyhjää tiedostoa (nolla sivua, tai tulostuksen ohjaus tiedostoon), jotta tulostukseen ei tulisi liian pitkää taukoa?
Kaatuu toisinaan vaikka ajaisi säännöllisin välein (30 sek) dataa tyhjään tiedostoon.
Uusi havainto. Kun laitan tällaisen rivin
Report.Database.Verify
ennen riviä Report.Database.SetDataSource adoPrintData, 3
niin ei näytä kaatuvan exe koskaan tulostettaessa koneellani, oli sitten taukoa tai ei.
Asiakkaan koneella ei kuitenkaan rivi .Verify toimi, vaan herjaa tuossa kohtaa puuttuvasta ODBC tietolähteen ohjaimesta.
Eli jotain häikkää rpt-pohjassa kuitenkin?
Auttaisikohan jos asentaisit asiakkaasi koneelle Microsoft Data Access Components (MDAC) -paketin.
Toinen todennäköinen ongelma liittyy 64-bittiseen järjestelmään. Miten tahansa, niin suosittelen siirtymään VB.NET / .NET Framework ympäristöön
Siirtyminen vb.nettiin ei välttämättä ratkaise ongelmaa, koska olen kuullut että tuossakin ympäristössä crystal kaatuu. Kyseessä siis voi olla crystalin bugi.
Tuosta MDAC paketista, laitatko linkin mistä sen voi ladata.
Tuosta sun linkkisivulta kun katsoo System Requirements, siellä ei mainita windows 7. Kai tuo seiskakoneisiinkin on asennettavissa?
Muuten, kuulin asiakkaalta että tulostus ei kaadu koskaan xp-koneilla, kaatuu vain win7. Eli ongelma liittyy myös 64-bittisyyteen.
Windows Vistassa ja Windows 7:ssa on valmiina tarvittavat komponentit (Windows DAC korvaa MDAC paketin). Ongelma saattaa piillä myös MSADO15.DLL -kirjaston versiossa. Mikäli on halua viritellä Crystalia 64-bittiselle järjestelmälle niin täältä löytyy kamaa/ohjeita 8.5 versiolle
täältä löytyy Crystal Reports 9.0 run-time 64-bittiselle Windowsille
Aihe on jo aika vanha, joten et voi enää vastata siihen.