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 FunctionMuoks #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 FunctionAihe on jo aika vanha, joten et voi enää vastata siihen.