2010-03-01 24 views
129

Necesito escribir un archivo en la misma carpeta donde reside una consola ClickOnce .application (archivo ejecutable). La carpeta desde donde se lanza.Cómo obtener la ruta de la carpeta para la aplicación ClickOnce

He intentado utilizar Application.StartupPath & Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) pero el camino está apuntando a una subcarpeta bajo c:\Documents & Settings. ¿Cómo obtengo el camino donde reside el .application?

Respuesta

3

ClickOnce applications DO residen en un subdirectorio de C: \ Documents & Configuración. No tienen directorios de instalación "limpios" porque los archivos locales se descargan "temporalmente" para permitir que la aplicación se ejecute en la PC local y la ejecución de la aplicación se controla desde el servidor ClickOnce en el que están implementados, dependiendo de la configuración de publicación. (Comprobación de actualizaciones, requisitos de versión, etc.).

+0

no tengo acceso a la carpeta C: \ Documents y carpeta Configuración del servidor que significa que no tengo acceso al archivo crea la aplicación. Ejecuto la aplicación desde cierta carpeta. Es la carpeta donde se publica la aplicación. ¿Cómo obtengo la ruta de esa carpeta? –

+0

Oh, quieres la URL de implementación. Lo siento, no lo entendí en absoluto. ¿Estás tratando de obtenerlo desde la aplicación ClickOnce o desde una aplicación externa? – RobinDotNet

107

ruta está apuntando a una subcarpeta en C: \ Documents & Ajustes

Eso es correcto. ClickOnce applications se instalan bajo el perfil del usuario que los instaló. ¿Tomó el camino que le dio la recuperación de la información del ensamblaje en ejecución y lo revisó?

en Windows Vista y Windows 7, se encuentra la caché de ClickOnce aquí:

c:\users\username\AppData\Local\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 

En Windows XP, lo encontrará aquí:

C:\Documents and Settings\username\LocalSettings\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 
+1

Entiendo todo esto. Quiero la carpeta desde donde hice clic en la aplicación. No tengo acceso a C: \ Documents and Settings, por lo tanto, no tendré acceso al archivo de registro si voy a utilizar la ruta de acceso de la carpeta devuelta por esa función y no deseo utilizar valores de ruta codificados . –

23

ApplicationDeployment.CurrentDeployment.ActivationUri podría funcionar

"Una cadena de longitud cero si la propiedad TrustUrlParameters en el manifiesto de implementación es falsa, o si el usuario ha proporcionado un UNC para abrir el despliegue o lo ha abierto loca lly. De lo contrario, el valor de retorno es el URL completo utilizado para iniciar la aplicación, incluyendo cualquier parámetro."


Pero lo que creo que realmente quiere es ApplicationDeployment.CurrentDeployment.DataDirectory que le da una carpeta que puede escribir datos. Cuando se actualiza De todos modos, la aplicación perderá lo que estaba en la carpeta .exe original, pero puede migrar el directorio de datos a una nueva versión de la aplicación. Su aplicación puede escribir en esta carpeta con cualquier archivo de registro que tenga, y estoy bastante seguro su escritura garantizada.

+2

+1 Para señalar DataDirectory. Gracias por eso –

+0

No hice nada, pero los archivos de DataDirectory anterior se copian automáticamente al nuevo DataDirectory después de la implementación. No hay directorios .pre también. (.NET Framework 3.5 y 4.5) –

197

Para encontrar la ubicación de la carpeta, puede ejecutar la aplicación, abrir el administrador de tareas (CTRL-SHIFT-ESC), seleccionar la aplicación y hacer clic derecho | Abrir la ubicación del archivo.

+2

hey, pro tip! pero no está disponible en las viejas y pésimas máquinas XP. :) – Jalal

+4

@Jalal para "máquinas viejas de mierda" vaya a www.SysInternals.com y descargue Process Explorer. Sospecho que los cambios en TaskManager de Win7 y luego Win8 simplemente se copiaron de él. –

+1

¿Cómo se logra esto en la aplicación que se ejecuta en la computadora del cliente? – user3285954

12

Estoy usando Assembly.GetExecutingAssembly().Location para obtener la ruta a una aplicación implementada ClickOnce en .Net 4.5.1.

Sin embargo, no debe escribir en ninguna carpeta donde se implemente su aplicación, independientemente del método de implementación (xcopy, ClickOnce, InstallShield, etc.) porque normalmente solo se leen para aplicaciones, especialmente en las versiones más recientes de Windows y entornos de servidor.

Una aplicación siempre debe escribir en las carpetas reservadas para tales fines. Puede obtener las carpetas que necesita desde Environment.SpecialFolder Enumeration.La página MSDN explica para qué sirve cada carpeta: http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx

I.e. para datos, registros y otros archivos, puede usar ApplicationData (itinerancia), LocalApplicationData (local) o CommonApplicationData. Para archivos temporales, use Path.GetTempPath o Path.GetTempFileName.

Lo anterior también funciona en servidores y escritorios.

EDITAR: Assembly.GetExecutingAssembly() se llama en el archivo ejecutable principal.

+0

Gran respuesta. Gracias – stigzler

+0

Esto me ha funcionado para una aplicación ClickOnce, y también para trabajar en el entorno de desarrollo VS mientras depuraba esa misma aplicación. – Developer63

0

Esto es lo que me encontré con que trabajaban para ser capaz de obtener la ubicación de la carpeta desplegada de mi aplicación ClickOnce y que no se ha mencionado en cualquier lugar que he visto en mis búsquedas, por mis semejantes, escenario específico:

  • La aplicación clickonce se implementa en la carpeta de red LAN de una empresa.
  • La aplicación clickonce está configurada para estar disponible en línea o sin conexión.
  • Mi URL de instalación de clickonce y las URL de actualización en las propiedades de mi proyecto no tienen nada especificado. Es decir, no hay una ubicación separada para la instalación o las actualizaciones.
  • En mis opciones de publicación, tengo un acceso directo de escritorio creado para la aplicación clickonce.
  • La carpeta a la que quiero acceder durante el inicio es aquella a la que quiero acceder mediante las versiones DEV, INT y PROD de la aplicación, sin cifrar la ruta.

Aquí es una representación visual de mi caso de uso:

enter image description here

  • Las carpetas en cajas azules son mis ubicaciones de directorio para la aplicación de cada del medio ambiente.
  • La carpeta en recuadro rojo es el directorio donde quiero obtener la ruta (que requiere primero obtener la ubicación de la carpeta desplegada de la aplicación "MyClickOnceGreatApp_1_0_0_37" que es lo mismo que el OP).

no he encontrado ninguna de las sugerencias en esta cuestión o sus comentarios a trabajar en la devolución de la carpeta que la aplicación ClickOnce se desplegó a (que entonces le mueva en relación con esta carpeta para buscar la carpeta de interés) . Ninguna otra búsqueda en Internet o preguntas relacionadas con SO aparecieron una respuesta tampoco.

Todas las propiedades sugeridas estaban fallando debido a que el objeto (por ejemplo, ActivationUri) era nulo o apuntaban a la carpeta de la aplicación instalada en caché de la PC local. Sí, podría manejar con gracia objetos nulos con un cheque de IsNetworkDeployed, eso no es un problema, pero sorprendentemente IsNetworkDeployed devuelve falso aunque de hecho tengo una ubicación de carpeta desplegada en la red para la aplicación clickonce. Esto se debe a que la aplicación se ejecuta desde los bits locales en caché.

La solución es mirar:

  • AppDomain.CurrentDomain.BaseDirectory cuando la aplicación se está ejecutando dentro de Visual Studio como desarrollar y
  • System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation mientras se esté ejecutando con normalidad.

System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation devuelve correctamente el directorio de red en el que se implementa mi aplicación Clickonce, en todos los casos. Es decir, cuando se puso en marcha a través de:

  • setup.exe
  • MyClickOnceGreatApp.application
  • El acceso directo del escritorio crea tras la primera instalación y puesta en marcha de la aplicación.

Aquí está el código que uso al inicio de la aplicación para obtener la ruta de la carpeta WorkAccounts. Conseguir la carpeta de la aplicación desplegada es simple por no marchar hasta directorios padre:

string directoryOfInterest = ""; 
if (System.Diagnostics.Debugger.IsAttached) 
{ 
    directoryOfInterest = Directory.GetParent(Directory.GetParent(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).FullName).FullName).FullName; 
} 
else 
{ 
    try 
    { 
     string path = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); 
     path = path.Replace("file:", ""); 
     path = path.Replace("/", "\\"); 
     directoryOfInterest = Directory.GetParent(Directory.GetParent(path).FullName).FullName; 
    } 
    catch (Exception ex) 
    { 
     directoryOfInterest = "Error getting update directory needed for relative base for finding WorkAccounts directory.\n" + ex.Message + "\n\nUpdate location directory is: " + System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); 
    } 
} 
1

Después de buscar información exhaustiva, por fin he encontrado una manera de encontrar los nombres de las carpetas ofuscado través del registro. He aquí un método simple para obtenerlos:

private static Tuple<string, string> GetClickonceDirectories() 
{ 
    var appToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0", "ComponentStore_RandomString", null); 
    var dataToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\StateManager", "StateStore_RandomString", null); 

    if (string.IsNullOrWhiteSpace(appToken) || string.IsNullOrWhiteSpace(dataToken)) 
    { 
     throw new Exception("Unable to find clickonce directories."); 
    } 

    var appDir = 
      [email protected]"{appToken.Substring(0, 8)}.{appToken.Substring(8, 3)}\{appToken.Substring(11, 8)}.{appToken.Substring(19, 3)}"; 

    var dataDir = 
      [email protected]"Data\{dataToken.Substring(0, 8)}.{dataToken.Substring(8, 3)}\{dataToken.Substring(11, 8)}.{dataToken.Substring(19, 3)}"; 

    var rootPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 
    rootPath = Path.Combine(rootPath, "Apps", "2.0"); 

    return new Tuple<string, string>(Path.Combine(rootPath, appDir), Path.Combine(rootPath, dataDir)); 
} 
Cuestiones relacionadas