Programowanie w Delphi7 - UAC


(scripter1) #1

Witam.

Piszę pewien program i napotkałem problem z prawami zapisu pod Vista i Win7.

Program ma tworzyć plik ustawień lub go usuwać (zależnie od akcji wybranej przez użytkownika) w folderze _C:\Users\%username%\AppData\Local\MyAppName_ ale niestety plik nie jest ani tworzony ani kasowany ani też nie ma żadnego komunikatu o błędzie.

Podejrzewam że to kwestia UAC i praw dostępu, potrzebuję pomocy w nadaniu mojemu programowi odpowiednich uprawnień.

Na kilku stronach napotkałem wzmianki o programie dodającym odpowiedni manifest do projektu delphi ale nie znalazłem nigdzie działającej jego wersji a Delphi7 którego używam posiada w komponentach jedynie xpmanifest.

Dodam jeszcze kod programu mam poprawny a ze względy na jego przeznaczenie nie mam możliwości wybrania innej ścieżki.


(Fiołek) #2

Folder lokalnych danych użytkownika nie jest chroniony przez UAC(dla aktualnie zalogowanego użytkownika). Problem leży gdzie indziej.

Rozwiązanie, które nie ma prawa nie działać: mt.exe z Windows SDK. Tworzysz sobie plik manifest(przykład, jak on ma wyglądać na MSDN) i w regułach "post-build"(nie wiem jak to się może nazywać w Twoim IDE) ręcznie dołączasz dany plik do EXE-ka(

mt.exe -manifest plik.manifest -updateresource:"ścieżka_do.exe;#1"

).


(scripter1) #3

Mógłbyś rozszerzyć myśl? Też mi się wydawało że nie powinno być problemów z dostępem do tego foldera ale jak widać się myliłem...

A nie chciałbym dołączać zewnętrznego pliku manifest bo program ma być programem typu one-file, poza tym win7 podobno często ignoruje zewnętrzne manifesty.


(Fiołek) #4

Nie potrzebujesz praw administratora, by mieć odstęp do danych użytkownika(C:\Users\%UserName%\AppData) - standardowo ACL ma taką postać:

System - pełna kontrola

Administratorzy - pełna kontrola

Właściciel(%username%) - pełna kontrola

, więc musiałeś coś ręcznie zmienić. Sprawdziłem u siebie(ACL mam takie jak wyżej, mogę tworzyć pliki programowo bez praw administratora).

Temat na TechNet pokazuje, jak to rozwiązać.

Dlatego poleciłem użyć narzędzia mt, które służy do osadzania manifestów. :wink:


(scripter1) #5

Problem właśnie w tym że ja nie mam visty/win7 tylko xp a testy na vista/win7 robię na kompach znajomych więc nie mogę nic im tam zmieniać...

Potrzebuję skutecznej metody umożliwiającej na vist i win7 tworzenie i usuwanie we wspomnianym folderze (w xp program operuje na innym folderze i nie ma żadnych problemów).

Prosiłbym o podanie przyczyn które mogłyby uniemożliwiać zapis w tym folderze.


(Fiołek) #6

Możesz, bo mają źle ustawione ACL dla tych folderów(i to nie jest problem programu, tylko błędu użytkownika) :wink:

Jeśli pod Vistą/7 używasz ścieżki zza czasów XP, to program nie zapisze danych w %LOCALAPPDATA%, tylko w %USERPROFILE%/Local Settings/Application Data, tak jak wskazałeś(do Documents and Settings jest link). Ścieżkę do odpowiedniego folderu możesz pobrać za pomocą SHGetKnownFolderPath(XP i wcześniejsze: SHGetFolderPath).


(Tomek Matz) #7

@scripter1

Mimo tego, że jesteś pewien, że program jest napisany dobrze, dodaj jakąś linijkę kodu, która będzie wyświetlać ścieżkę, pod którą następuje próba zapisania pliku konfiguracyjnego i poproś osobę, która testuje Twój program, żeby odczytała Ci tą ścieżkę. Jeśli ścieżka okaże się poprawna, to zapytaj ją czy przypadkiem nie odpala programu w jakiejś piaskownicy. Jeśli nie jest odpalany w piaskownicy, to poproś tą osobę, aby spróbowała odpalić program na innym koncie użytkownika, np. na dopiero co utworzonym.

Możesz też ściągnąć http://technet.microsoft.com/pl-pl/evalcenter/cc442495.aspx testową wersję Windows 7 i zainstalować ją sobie, np. na wirtualnej maszynie, tak żebyś mógł testować samodzielnie. Wymogiem jest jednak posiadanie konta w usłudze Live. Po drodze będziesz też musiał wypełnić jakąś ankietę (ja jej do końca nie wypełniałem).


(scripter1) #8

To zrobiłem na samym początku jak tylko okazało się że coś jest nie tak dlatego napisałem że kod jest poprawny.

To by był dobry pomysł ale nie mam tam konta a nie będę się rejestrował tylko po to, i tak już walczę z jednym portalem bo nie chcą usunąć mojego konta mimo wyraźnego żądania...


(Tomek Matz) #9

@scripter1

A co z tą piaskownicą i próbą odpalenia programu na koncie innego użytkownika (najlepiej nowego)?


(scripter1) #10

Według moich ostatnich testów okazuje się że to nie prawa zapisu są problemem tylko samo deklarowanie ścieżki ze zmienną windowsową.

Po zadeklarowaniu pełnej ścieżki statycznie (do testu) z nazwą usera na którego koncie jest testowane okazało się że działa, teraz tylko muszę zastosować jakąś skuteczną metodę odczytu tej nazwy usera.


(Tomek Matz) #11

Czyli Ty do metody odpowiedzialnej za zapis do pliku przekazywałeś ścieżkę w postaci "C:\Users\%username%\AppData\Local\MyAppName\" (dokładnie takiej) ? Przecież to jest oczywiste, że to nie może być dobrze. Chyba, że ta metoda samodzielnie dokonywałyby parsowania tej ścieżki, ale to wówczas musiałoby być opisane w dokumentacji. A tak w ogóle to katalog użytkowników nie musi znajdować się na partycji C. Poszukaj metody, która służy do odczytywania wartości zmiennych środowiskowych (ja nie znam Delphi) i odczytuj ścieżkę dla %LOCALAPPDATA%.


(Fiołek) #12

Delphi jak mniemam potrafi dostać się do funkcji WinAPI?

Czyli kod NIE JEST poprawny.

Serio uchowałeś się tyle czasu bez Live ID? O.o


(scripter1) #13

Fiołek , kod jest poprawny tylko moja wiedza na temat visty/win7 jest ograniczona ze względu na to że nie mam ani visty ani win7.

I tu włąśnie dochodzimy do meritum bo mój program operuje na ustawieniach innego programu i nie wiem jak dokładnie tamten się odwołuje (czy przez zmienną systemową %LOCALAPPDATA% czy też przez inną) ale wiem że plik na którym ma operować mój program znajduje się właśnie w podanej wyżej przeze mnie ścieżce.

Zakładam że pewnie odwołuje się on do zmiennej %LOCALAPPDATA% bo jakby się odwoływał przez %username% to podejrzewam że by wywalał errory na systemach gdzie faktycznie ten folder nie jest w c:\Users.

W sumie to pierwotnie też odwoływałem się przez %LOCALAPPDATA% ale jak nie działało to zacząłem kombinować inaczej.

PS: Fiołek , uchowałem się i jak już napisałem nie zamierzam tego zmieniać, Live ID jest mi absolutnie zbędne.

-- Dodane 15.07.2011 (Pt) 22:50 --

Problem rozwiązany, dziękuję za pomoc.

W razie jakby ktoś szukał rozwiązania to zamieszczam kod który wykorzystałem:

uses:

   ShlObj;


function GetSpecialFolderPath(Folder: Integer; CanCreate: Boolean): string;


var

   FilePath: array [0..255] of char;


begin

 SHGetSpecialFolderPath(0, FilePath, FOLDER, CanCreate);

 Result := FilePath;

end;

Funkcję wywołuję poprzez:

GetSpecialFolderPath ($001c, false);