Was bestimmt den Rückgabewert von Path.GetTempPath ()?

73

Derzeit verwende ich, Path.GetTempPath()um herauszufinden, wo meine Protokolldateien geschrieben werden sollen. Vor kurzem bin ich jedoch auf einen Computer eines Benutzers gestoßen, auf dem der zurückgegebene Pfad nicht den Erwartungen entsprach.

Normalerweise lautet der zurückgegebene Pfad C: \ Dokumente und Einstellungen \ [Benutzer-ID] \ Lokale Einstellungen \ Temp. In diesem Fall war dies jedoch C: \ Temp

Dies wäre normalerweise kein Problem, aber aus irgendeinem Grund hatte der betreffende Benutzer keinen Zugriff zum Schreiben in C: \ Temp

Ich habe die Umgebungsvariablen doppelt überprüft, und die Umgebungsvariable USER zeigte erwartungsgemäß auf C: \ Dokumente und Einstellungen \ [Benutzer-ID] \ Lokale Einstellungen \ Temp , während die Umgebungsvariable SYSTEM auf C: \ WINNT \ Temp zeigte .

Also ... woher kommt Path.GetTempPath()der Wert? Gruppenrichtlinie? Registrierung?

Ich habe gegoogelt, aber ohne Erfolg.

Andy Blackman
quelle
8
+1 Schnelle, saubere, klare, gute Frage - Willkommen bei StackOverflow
Nick Craver
wenn Sie einen sicheren Ort benötigen , die ist immer beschreibbar für einen Benutzer Besuche getrennte Lagerung: msdn.microsoft.com/en-us/library/bdts8hk0.aspx
marc_s
1
@marc_s: Wenn FIPS nicht aktiviert ist, erhalten Sie in diesem Fall eine Ausnahme, wenn Sie versuchen, IsolatedStorage zu verwenden
adrianbanks
@adrian: interessant - danke für diesen Zeiger. Zum ersten Mal höre ich so etwas (wahrscheinlich seit wir hier in Europa sind uns "FIPS" und so nicht wirklich
wichtig

Antworten:

62

(Using Reflector) Path.GetTempPath()ruft letztendlich die Win32-Funktion GetTempPath (von kernel32.dll) auf. Die MDSN-Dokumente für diesen Status:

Die GetTempPath-Funktion überprüft das Vorhandensein von Umgebungsvariablen in der folgenden Reihenfolge und verwendet den ersten gefundenen Pfad:

  • Der von der TMP-Umgebungsvariablen angegebene Pfad.
  • Der von der Umgebungsvariablen TEMP angegebene Pfad.
  • Der von der Umgebungsvariablen USERPROFILE angegebene Pfad.
  • Das Windows-Verzeichnis.

Beachten Sie, dass sie auch angeben, dass nicht überprüft wird, ob der Pfad tatsächlich vorhanden ist oder in den geschrieben werden kann , sodass Sie möglicherweise versuchen, Ihre Protokolldateien in einen Pfad zu schreiben, der nicht vorhanden ist oder auf den Sie nicht zugreifen können .

adrianbanks
quelle
Gute Antwort! Klar, präzise und genau die Informationen, die ich brauchte. Ich hatte nicht daran gedacht, die Win32-Funktionsdokumente zu überprüfen ... Vielen Dank. Andy
Andy Blackman
1
Neuere Dokumentationen für Path.GetTempPath()haben unter Bemerkungen einen sehr ähnlichen Inhalt.
Chwarr
Dies ist nicht der Fall. Ich habe gerade meine Umgebungsvariablen wiederholt, sie in den Systemeigenschaften überprüft und einen Path.GetTempPath () erstellt. Sie sind nicht identisch: imgbox.com/L1CDsEBe
Tod
16

Haftungsausschluss: Keine Antwort - aber wichtige Lektüre!

Es ist sehr wichtig zu wissen, dass Sie Ihre temporären Dateien löschen müssen, da das Framework nicht mehr erstellt wird und Ihre App explodiert, wenn Sie 65536 in einem einzelnen Verzeichnis drücken!

Sie werden sich über Monate und Monate ansammeln und dann erhalten Sie eine Nachricht wie folgt:

System.IO.IOException: The file exists.

  at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
  at System.IO.__Error.WinIOError()
  at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
  at System.IO.Path.GetTempFileName():

und TFS gibt Ihnen Folgendes, wenn Sie versuchen zu erstellen:

TF215097: An error occurred while initializing a build for build 
definition XXXXX: The file exists. 

Alles, was Sie tun müssen, ist, zum Path.GetTempPath()Ordner zu navigieren und anzurufendel tmp*

Hinweis: Wenn Sie eine ASP.NET-Anwendung haben, die temporäre Dateien erstellt, unterscheidet sich das temporäre Verzeichnis wahrscheinlich vom aktuell angemeldeten Benutzer

Im Zweifelsfall (oder in Panik) erstellen Sie einfach eine Aspx-Seite, um den verwendeten Speicherort auszudrucken:

 TempPath.aspx
 <%@ Page Language="C#"%>
 Temp path: <%= System.IO.Path.GetTempPath() %>

Für mich beim Laufen wie NetworkServiceich bekomme

 C:\Windows\TEMP\

Bei der Ausführung als AppPool (mit dem Namen www.example.com) kann der Pfad wie folgt lauten:

 C:\Users\www.example.com\AppData\Local\Temp

PS. Ich denke, dies kann auch dann passieren, wenn Sie die Datei anschließend löschen, da der Dateiname zunimmt.

Simon_Weaver
quelle
10
Bin heute Morgen mit totem Produktionssystem ins Büro gekommen. Es stellte sich heraus, dass einer unserer Entwickler Path.GetTempFileName () verwendet hat, um zufällige Dateinamen zu generieren, die an anderer Stelle verwendet werden sollen. Er wusste nicht, dass es auch eine Null-Byte-Datei in c: \ windows \ temp erstellt. Das System muss versucht haben, seine 65537. Datei zu erstellen! Dieser Kommentar ersparte uns stundenlange Ausfallzeiten. Vielen Dank für die Veröffentlichung vor 2 Jahren!
cjuk
1
Für zukünftige Überprüfungen: Wie ich mich erinnere, gibt die Path.GetTempFileName () -Methode nur so etwas wie "_00001.tmp" zurück und erhöht sich bei jedem Aufruf um 1 .. Wenn "_65537.tmp" angezeigt wird - Die maximale Anzahl von Dateien - wird der nächste Aufruf versucht um "_00001.tmp" zurückzugeben, wenn die Datei nicht existiert. Wenn vorhanden, dann wird ein Fehler ausgegeben. Also ist es besser, den temporären Dateinamen-Cache sauber zu halten {einfach, wenn Sie ihn nicht mehr benötigen, löschen Sie einfach die Datei}.
Ich
Ich mag es, es unter 32000 Dateien zu halten, nur um auf der sicheren Seite zu sein ;-) Ich habe immer noch nicht herausgefunden, warum das sofortige Löschen meiner tmp-Datei sie nicht wirklich löscht - und es wird kein Backup oder Virenschutz ausgeführt, der zu Sperren führen kann Dateien.
Simon_Weaver
Vielen Dank an alle, die heute zufällig positiv bewertet wurden. Ich habe nachgesehen und bin wieder bis zu 31480 Dateien!
Simon_Weaver
2

Ich habe festgestellt, dass GetTempPath () den Pfad "Dokumente und Einstellungen \ Benutzer \ Lokale Einstellungen \ Temp" des lokalen Benutzers wiederherstellen kann, wenn es sich um eine Konsolenanwendung handelt, und festgestellt, dass C: \ WINDOWS \ Temp (auf dem Server) wiederhergestellt werden kann, wenn es sich um einen handelt Web-App wird von einem Client ausgeführt. Im ersteren Fall keine große Sache - das Konto, auf dem die App ausgeführt wird, hat die Rechte für diesen Ordner. In letzterem Fall ist es möglicherweise eine große Sache, wenn das App Pool Identity-Konto (oder das Konto, mit dem Sie sich in der Datei Web.config für die Web-App ausgeben) keine Berechtigungen für C: \ WINDOWS \ Temp on hat der Server (was eine große Chance ist, dass dies nicht der Fall ist). Für meine Konsolen-Apps ist es also keine Frage, wo temporäre Dateien geschrieben werden. Das Hardcodieren eines Strings in eine INI-Datei ist für mich am besten und einfachsten, und für eine Web-App ist das Hardcodieren im Web.

public static string findFileDirectory(string file)
{
    // Get the directory where our service is being run from
    string temppath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    // Ensure proper path notation so we can add the INI file name
    if (!temppath.EndsWith(@"\")) temppath += @"\";

    return temppath;
}

und nenne es so:

    string tempFolderPath = findFileDirectory("Web.config");
    tempFolderPath = tempFolderPath.Replace(@"\\", @"\");

und verwenden Sie einfach "tempFolderPath" anstelle der Stelle, an der Sie zuvor Path.GetTempPath () verwendet haben. Diese Funktion funktioniert hervorragend und ich verwende sie in meinem Code anstelle dieser bösen GetTempPath () -Methode, damit ich weiß, dass meine App das tun kann, was sie tun muss, da der Ordner ASP Temp Files alle Berechtigungen haben sollte, die er für seine Operationen benötigt ( DOMAIN \ NETWORK SERVICE und App Pool ID-Konto benötigen Vollzugriff. tempFolderPath endet mit einem abschließenden Schrägstrich. Konzentrieren Sie sich also direkt mit Ihrem Variablen- / Dateinamen, um den richtigen Pfad zu finden.

-Tom

PS Sie müssen zwei Namespaces hinzufügen, damit diese Funktion funktioniert: System.IO und System.Reflection

Tom
quelle
2

Bitte versuchen Sie Folgendes zu verwenden, um den geeigneten Ort für Ihre Daten zu bestimmen:

Environment.GetFolderPath(Environment.SpecialFolder folder);

Wo Spezialordner

// Summary:
//     Specifies enumerated constants used to retrieve directory paths to system
//     special folders.
[ComVisible(true)]
public enum SpecialFolder
{
  // Summary:
  //     The logical Desktop rather than the physical file system location.
  Desktop = 0,
  //
  // Summary:
  //     The directory that contains the user's program groups.
  Programs = 2,
  //
  // Summary:
  //     The directory that serves as a common repository for documents.
  Personal = 5,
  //
  // Summary:
  //     The "My Documents" folder.
  MyDocuments = 5,
  //
  // Summary:
  //     The directory that serves as a common repository for the user's favorite
  //     items.
  Favorites = 6,
  //
  // Summary:
  //     The directory that corresponds to the user's Startup program group.
  Startup = 7,
  //
  // Summary:
  //     The directory that contains the user's most recently used documents.
  Recent = 8,
  //
  // Summary:
  //     The directory that contains the Send To menu items.
  SendTo = 9,
  //
  // Summary:
  //     The directory that contains the Start menu items.
  StartMenu = 11,
  //
  // Summary:
  //     The "My Music" folder.
  MyMusic = 13,
  //
  // Summary:
  //     The directory used to physically store file objects on the desktop.
  DesktopDirectory = 16,
  //
  // Summary:
  //     The "My Computer" folder.
  MyComputer = 17,
  //
  // Summary:
  //     The directory that serves as a common repository for document templates.
  Templates = 21,
  //
  // Summary:
  //     The directory that serves as a common repository for application-specific
  //     data for the current roaming user.
  ApplicationData = 26,
  //
  // Summary:
  //     The directory that serves as a common repository for application-specific
  //     data that is used by the current, non-roaming user.
  LocalApplicationData = 28,
  //
  // Summary:
  //     The directory that serves as a common repository for temporary Internet files.
  InternetCache = 32,
  //
  // Summary:
  //     The directory that serves as a common repository for Internet cookies.
  Cookies = 33,
  //
  // Summary:
  //     The directory that serves as a common repository for Internet history items.
  History = 34,
  //
  // Summary:
  //     The directory that serves as a common repository for application-specific
  //     data that is used by all users.
  CommonApplicationData = 35,
  //
  // Summary:
  //     The System directory.
  System = 37,
  //
  // Summary:
  //     The program files directory.
  ProgramFiles = 38,
  //
  // Summary:
  //     The "My Pictures" folder.
  MyPictures = 39,
  //
  // Summary:
  //     The directory for components that are shared across applications.
  CommonProgramFiles = 43,
}
Wojtek Turowicz
quelle
2

Wenn Sie mit C#auf MacOSverwenden Mono Frameworkdann zurückgegebene Wert von Path.GetTempPath()ist Wert der UmgebungsvariablenTMPDIR .

Beim Ausführen wird echo $TMPDIRnormalerweise der folgende Wert zurückgegeben:

/var/folders/{2 character random-string}/{random-string}/T
doer_uvc
quelle
1

Es ruft die GetTempPath- Funktion auf. In der Dokumentation wird erläutert, welche Umgebungsvariablen überprüft werden.

Arve
quelle