Miten saa selville missä kansiossa ajettava ohjelmaa suoritetaan.
Kun pitäisi tehdä ohjelmalla tiedosto samaan kansioon missä ajettava ohjelma on
Open "testi.txt" For Output #1
Tuolla se tulee samaan kansioon, mutta jos ohjelmalla on CommonDialog komponentilla availlut muita tiedostoja jostain muusta kansiosta, se tekee tuon testi.txt tiedoston sinne kansioon mistä viimeksi CommonDialog:lla on avattu jotain.
Ajatuksena on, että ei etukäteen tiedä mihin kansioon ohjelma on asenettu.
Ohjelman hakemisto on muuttujassa App.Path:
MsgBox App.Path
Se oli nopea vastaus, kiitän.
Muista sitten, että Vistassa ei muuttuvia tiedostoja saa tallennella Program Files -hakemistoon, joten tallennuskelpoiset kansiot pitää hakea API-kutsuilla (esim. XP:ssä "C:\Documents and Settings\Käyttäjä\Application Data\Ohjelman nimi"
kun taas Vistassa jokseenkin tyyliä "C:\Users\Käyttäjä\AppData\Local\Ohjelman nimi"
).
Muoks!
Tässä on Unicodea tukeva versio; käyttäjän nimessä kun voi olla vaikka mitä merkkejä.
Option Explicit Private Declare Function BStrW Lib "oleaut32" Alias "SysAllocStringLen" (ByVal Ptr As Long, ByVal Length As Long) As Long Private Declare Sub CoTaskMemFree Lib "ole32" (ByVal pvoid As Long) Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal Ptr As Long, ByVal Value As Long) Private Declare Function SHGetPathFromIDListW Lib "shell32" (ByVal Pidl As Long, ByVal pszPath As Long) As Long Private Declare Function SHGetSpecialFolderLocation Lib "shell32" (ByVal hWnd As Long, ByVal nFolder As Long, ppidl As Long) As Long Private Const CSIDL_PERSONAL = &H5 Private Const CSIDL_DESKTOPDIRECTORY = &H10 Private Const CSIDL_APPLICATIONDATA = &H1A Private Const MAX_PATH = 260 Public Function AppData() As String Dim lngIDL As Long, lngPtr As Long ' selvitä hakemiston sijainti If SHGetSpecialFolderLocation(0, CSIDL_APPLICATIONDATA, lngIDL) = 0 Then ' luo 260 merkkiä pitkä merkkijonobufferi lngPtr = BStrW(0, MAX_PATH) ' aseta se funktiosta palautettavaan muuttujaan PutMem4 VarPtr(AppData), lngPtr ' täytä bufferi hakemistolla If SHGetPathFromIDListW(lngIDL, lngPtr) Then ' lyhennä merkkijonoa mikäli merkkijonossa on null If InStr(AppData, vbNullChar) Then AppData = Left$(AppData, InStr(AppData, vbNullChar) - 1) Else ' tapahtui virhe, poista bufferi AppData = vbNullString End If End If ' vapauta luotu resurssi CoTaskMemFree lngIDL End Function
Muoks #2!
Olen muuten kannettavallani sumplinut XP:n käyttäjähakemistot ihan uuteen uskoon, joten siinä koneessa on Application Data vielä vähän eri paikassa. Se on vähän Vistamaisempi, mutta välissä on vielä semmoinen piilohakemisto kuin Järjestelmä. Joten tosiaan ei kannata luottaa sokeasti siihen, että jokin hakemisto on tasan tietyssä muodossa.
"Muista sitten, että Vistassa ei muuttuvia tiedostoja saa tallennella Program Files -hakemistoon"
Mikäs tossa on juonena, että noin ei saa tehdä?
Olen Inno Setup:lla tehnyt asennusohjelman joka on c: juureen tehnyt ohjelmalle kansion ja asentanut sinne ohjelman ja ohjelmassa tarvittavat muokattavat tiedostot.
Onko se väärin?
Milu kirjoitti:
"Muista sitten, että Vistassa ei muuttuvia tiedostoja saa tallennella Program Files -hakemistoon"
Mikäs tossa on juonena, että noin ei saa tehdä?
Olen Inno Setup:lla tehnyt asennusohjelman joka on c: juureen tehnyt ohjelmalle kansion ja asentanut sinne ohjelman ja ohjelmassa tarvittavat muokattavat tiedostot.
Onko se väärin?
Ei se väärin ole, asennusohjelma pyytää vain tällöin UACilta järjestelmänvalvojan oikeudet asennusta varten, joka on joidenkin mielestä ärsyttävää. Mikäköhän siinä on kun liinuksien sudoihin ynnä muihin vastaaviin ei suhtauduta yhtä negatiivisesti. :/ Tietoturvatietoturva.
Kyseessä on ihan Microsoftin suositukset siitä, miten ohjelmia tulisi tehdä Windowsiin. Nämä suositukset ovat olleet olemassa samantapaisina pitkän tovin, mutta vasta Vistan myötä Microsoft valitsi jyrkemmän linjan: ohjelmat jotka on koodattu "huonosti" eivät saakaan enää toimia yhtä vapaasti kuin aiemmin. Helpoin oikotie onneen on kytkeä pois UAC tai antaa käyttäjälle järjestelmänvalvojan oikeudet, mutta tämä ei ole tietoturvan kannalta ollenkaan järkevää.
Application Data on se paikka minne tallennetaan ohjelman tarvitsemia asetus ym. tiedostoja. Käyttäjän hakemistoon taas tulisi tallentaa käyttäjän omia tiedostoja. Program Filesissa sijaitsevat kiinteät ohjelman ajamiseen tarvittavat tiedostot, jotka eivät muutu paitsi päivitettäessä ohjelmaa.
Heippa taas!
tota API-purkaa voi lyhentää huomattavasti lisäämällä projektiin viittauksen tyyppikirjastoon - Mircrosoft WMI Scripting V1.2 Library (C:\Windows\System32\wbem\wbemdisp.tlb) - viittausta ei tarvitse käyttää mikäli rekisteröi ko. tyyppikirjaston esim. regtlib.exe ohjelmalla...
pikku esimerkki...
Private Sub Command1_Click() 'muutama hexa... 'Desktop - &H0 'Personal - &H5 'Appdata - &H1A Dim FullPath As String Dim FileName As String FileName = "Test.txt" FullPath = GetSpecialFolderPath(&H0) & "\" & FileName Open FullPath For Output As #1 Print #1, "Jee...": Close #1 Shell "Notepad.exe " & FullPath, vbNormalFocus Kill FullPath End Sub Function GetSpecialFolderPath(HexVal As Variant) As String Set objShell = CreateObject("Shell.Application") Set objFolder = objShell.Namespace(HexVal) GetSpecialFolderPath = objFolder.Self.Path Set objFolder = Nothing Set objShell = Nothing End Function
Aihe on jo aika vanha, joten et voi enää vastata siihen.