Automatisch den Pfad zu einer anderen Anwendung ermitteln lassen

  • VB6
  • .NET (FX) 4.5–4.8

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von StolleJay.

    Automatisch den Pfad zu einer anderen Anwendung ermitteln lassen

    Ich habe mal wieder eine kleine Frage.
    Wie kann ich meinem Programm beibringen auf dem PC Automatisch den Pfad zu einem Programm (also zu dessen .exe) zu suchen und diesen Pfad dann in die My.Settings.xxx Speichern?
    Derzeit Löse ich es simple via FolderBrowserDialog doch ich würde den Usern diese Aufgabe gern Abnehmen. Das Problem ist das diese Externe Anwendung bei jedem Usern wo anders Installiert ist.

    Ich habe es schon via Registry versucht doch die Externe Anwendung hinterlässt in der Registry keine Pfadangabe.

    Habt ihr da eine Lösung dafür?
    Wenn es immer woanders ist, dann ist das schier unmöglich, von daher muss der User das selbst machen, ganz einfach.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ja, Bruno, ich weiß, Du bist ein Optimist, aber das war jetzt der grundlegende Gedanke. Wäre halt am Einfachsten ;)
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Na ja, wenn man den Aufwand bedenkt, dass alles zu druchsuchen und dabei noch gute Performance hinzulegen usw. ist es schon viel. Zudem können sich da haufen Probleme einschleichen. Da ist es doch einfacher den User das wählen zu lassen, oder?
    Das ist gut performant und es macht eig jedes Programm so.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Trade schrieb:

    Na ja, wenn man den Aufwand bedenkt, dass alles zu druchsuchen und dabei noch gute Performance hinzulegen usw. ist es schon viel. Zudem können sich da haufen Probleme einschleichen.

    Deine Bedenken sind natürlich angebracht, jedoch ist alles relativ - auch diese Problematik :) ..

    Ein Beispiel, dass ich eben mal zum Test entwickelt habe. Ist sicher verbesserungsbedürftig, aber so auf die Schnelle tuts ganz gut!
    Das Programm sucht die ganze C-Partition nach einem Filenamen ab, den man eingeben kann. Eine Ausweitung auf alle fixen Partitionen ist bereits vorgesehen und derzeit auskommentiert. Es soll ja nur zur Veranschaulichung dienen.

    C# Version:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Diagnostics;
    4. using System.IO;
    5. using System.Runtime.InteropServices;
    6. namespace fixedIndex
    7. {
    8. class Program
    9. {
    10. static void Main(string[] args)
    11. {
    12. Console.Write("\r\nNach welcher Datei suchen wir?: ");
    13. string strSearch = Console.ReadLine();
    14. Console.WriteLine("Die Suche nach " + strSearch + " beginnt..\r\n");
    15. // Start watch
    16. Stopwatch watch = Stopwatch.StartNew();
    17. //// Get all drives
    18. //DriveInfo[] drives = DriveInfo.GetDrives();
    19. //// Go through the drives
    20. //foreach (var drive in drives)
    21. //{
    22. // // Drive is ready?
    23. // if (drive.DriveType == DriveType.Fixed && drive.IsReady)
    24. // {
    25. // Console.WriteLine(drive.Name);
    26. // }
    27. //}
    28. // Search for files
    29. List<string> fList = getFiles(@"C:\", strSearch);
    30. // Go through the files
    31. foreach (string foundFiles in fList)
    32. Console.WriteLine(foundFiles.ToString());
    33. // Stop watch, write stats
    34. watch.Stop();
    35. Console.WriteLine("\r\n- FERTIG in " + watch.ElapsedMilliseconds.ToString("N") + " Sek.-");
    36. Console.ReadKey();
    37. }
    38. /// <summary>
    39. /// Find files
    40. /// </summary>
    41. /// <param name="rootDirectory">Start directory</param>
    42. /// <param name="searchPattern">You search for..</param>
    43. /// <returns>Files</returns>
    44. private static List<string> getFiles(string rootDirectory, string searchPattern)
    45. {
    46. List<string> fileList = new List<string>();
    47. IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    48. WIN32_FIND_DATA findData;
    49. IntPtr findHandle;
    50. findHandle = FindFirstFile(@"\\?\" + rootDirectory + @"\*", out findData);
    51. if (findHandle != INVALID_HANDLE_VALUE)
    52. {
    53. do // Directory
    54. {
    55. if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    56. {
    57. if (findData.cFileName != "." && findData.cFileName != "..")
    58. fileList.AddRange(getFiles(string.Concat(rootDirectory, (rootDirectory.EndsWith(@"\") ? "" : @"\"), findData.cFileName), searchPattern));
    59. }
    60. else // Files
    61. {
    62. if (Path.GetFileName(findData.cFileName) == searchPattern)
    63. fileList.Add(string.Concat(rootDirectory, (rootDirectory.EndsWith(@"\") ? "" : @"\"), findData.cFileName));
    64. }
    65. }
    66. while (FindNextFile(findHandle, out findData));
    67. FindClose(findHandle);
    68. }
    69. return fileList;
    70. }
    71. private const int MAX_PATH = 260;
    72. private const int MAX_ALTERNATE = 14;
    73. private const int FILE_ATTRIBUTE_DIRECTORY = 0x10;
    74. [StructLayout(LayoutKind.Sequential)]
    75. private struct FILETIME
    76. {
    77. public uint dwLowDateTime;
    78. public uint dwHighDateTime;
    79. };
    80. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    81. private struct WIN32_FIND_DATA
    82. {
    83. public uint dwFileAttributes;
    84. public FILETIME ftCreationTime;
    85. public FILETIME ftLastAccessTime;
    86. public FILETIME ftLastWriteTime;
    87. public uint nFileSizeHigh;
    88. public uint nFileSizeLow;
    89. public uint dwReserved0;
    90. public uint dwReserved1;
    91. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
    92. public string cFileName;
    93. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)]
    94. public string cAlternate;
    95. }
    96. [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    97. private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
    98. [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    99. private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
    100. [DllImport("kernel32.dll")]
    101. private static extern bool FindClose(IntPtr hFindFile);
    102. }
    103. }


    VB.NET Version:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Collections.Generic
    3. Imports System.Diagnostics
    4. Imports System.IO
    5. Imports System.Runtime.InteropServices
    6. Module Module1
    7. Sub Main()
    8. Console.Write(vbCr & vbLf & "Nach welcher Datei suchen wir?: ")
    9. Dim strSearch As String = Console.ReadLine()
    10. Console.WriteLine("Die Suche nach " & strSearch & " beginnt.." & vbCr & vbLf)
    11. ' Start watch
    12. Dim watch As Stopwatch = Stopwatch.StartNew()
    13. '' Get all drives
    14. 'Dim drives As DriveInfo() = DriveInfo.GetDrives()
    15. 'For Each drive As DriveInfo In drives
    16. ' ' Drive is fixed and ready?
    17. ' If drive.DriveType = DriveType.Fixed AndAlso drive.IsReady Then
    18. ' Console.WriteLine(drive.Name)
    19. ' End If
    20. 'Next
    21. ' Search for files
    22. Dim fList As List(Of String) = getFiles("C:\", strSearch)
    23. ' Go through the files
    24. For Each foundFiles As String In fList
    25. Console.WriteLine(foundFiles.ToString())
    26. Next
    27. ' Stop watch, write stats
    28. watch.[Stop]()
    29. Console.WriteLine(vbCr & vbLf & "- FERTIG in " & watch.ElapsedMilliseconds.ToString("N") & " Sek. -")
    30. Console.ReadKey()
    31. End Sub
    32. ''' <summary>
    33. ''' Find files
    34. ''' </summary>
    35. ''' <param name="rootDirectory">Start directory</param>
    36. ''' <param name="searchPattern">You search for..</param>
    37. ''' <returns>Files</returns>
    38. Private Function getFiles(rootDirectory As String, searchPattern As String) As List(Of String)
    39. Dim fileList As New List(Of String)()
    40. Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
    41. Dim findData As WIN32_FIND_DATA
    42. Dim findHandle As IntPtr
    43. findHandle = FindFirstFile("\\?\" & rootDirectory & "\*", findData)
    44. If findHandle <> INVALID_HANDLE_VALUE Then
    45. Do
    46. ' Directory
    47. If (findData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) <> 0 Then
    48. If findData.cFileName <> "." AndAlso findData.cFileName <> ".." Then
    49. fileList.AddRange(getFiles(String.Concat(rootDirectory, (If(rootDirectory.EndsWith("\"), "", "\")), findData.cFileName), searchPattern))
    50. End If
    51. Else
    52. ' Files
    53. If Path.GetFileName(findData.cFileName) = searchPattern Then
    54. fileList.Add(String.Concat(rootDirectory, (If(rootDirectory.EndsWith("\"), "", "\")), findData.cFileName))
    55. End If
    56. End If
    57. Loop While FindNextFile(findHandle, findData)
    58. FindClose(findHandle)
    59. End If
    60. Return fileList
    61. End Function
    62. Private Const MAX_PATH As Integer = 260
    63. Private Const MAX_ALTERNATE As Integer = 14
    64. Private Const FILE_ATTRIBUTE_DIRECTORY As Integer = &H10
    65. <StructLayout(LayoutKind.Sequential)> _
    66. Private Structure FILETIME
    67. Public dwLowDateTime As UInteger
    68. Public dwHighDateTime As UInteger
    69. End Structure
    70. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    71. Private Structure WIN32_FIND_DATA
    72. Public dwFileAttributes As UInteger
    73. Public ftCreationTime As FILETIME
    74. Public ftLastAccessTime As FILETIME
    75. Public ftLastWriteTime As FILETIME
    76. Public nFileSizeHigh As UInteger
    77. Public nFileSizeLow As UInteger
    78. Public dwReserved0 As UInteger
    79. Public dwReserved1 As UInteger
    80. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> Public cFileName As String
    81. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_ALTERNATE)> Public cAlternate As String
    82. End Structure
    83. <DllImport("kernel32.dll", CharSet:=CharSet.Unicode)> _
    84. Private Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
    85. End Function
    86. <DllImport("kernel32.dll", CharSet:=CharSet.Unicode)> _
    87. Private Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
    88. End Function
    89. <DllImport("kernel32.dll")> _
    90. Private Function FindClose(hFindFile As IntPtr) As Boolean
    91. End Function
    92. End Module


    Wenn ich z.B. nach shell32.dll suche, bringt er mir alle Treffer in 2,2 Sekunden. Dabei werden über 200.000 Files in allen Unterverzeichnissen durchsucht.
    Exceptions gibts nicht, auch nicht bei "kritischen" Verzeichnissen!

    Das ist doch durchaus ausbaufähig und performant - finde ich.
    Wenn man das noch in einen eigenen Thread packt, ist die Suche durch, bevor der User das Programm beäugelt hat :D .



    LG,
    Bruno

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „diylab“ ()

    Ganzen PC nach Datei durchsuchen ! - Alle Platten durchsuchen !

    Form1:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Dim f As SearchFile
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. 'xxx
    6. End Sub
    7. Private Sub Button1_Click(ByVal sender As System.Object, _
    8. ByVal e As System.EventArgs) Handles Button1.Click
    9. ' alle logischen LW nach der Datei durchsuchebn,
    10. ' die in der TextBox eingegeben wurde
    11. f = New SearchFile(TextBox1.Text, System.Environment.GetLogicalDrives, True)
    12. AddHandler f.CurrentFile, AddressOf CurrentFile
    13. f.Search()
    14. End Sub
    15. Private Sub CurrentFile(ByVal FileName As String, ByVal IsEqual As Boolean)
    16. ' Pfad extrahieren und im Label-Control anzeigen
    17. Dim sPath As String = IO.Path.GetDirectoryName(FileName)
    18. If Label1.Text <> sPath Then
    19. Label1.Text = sPath
    20. Application.DoEvents()
    21. End If
    22. ' Treffer der ListBox hinzufügen
    23. If IsEqual Then
    24. Me.ListBox1.Items.Add(FileName)
    25. Application.DoEvents()
    26. ' Falls nach dem 1. Treffer der Vorgang abgebrochen
    27. ' werden soll, einfach die Abort-Methode aufrufen
    28. ' f.Abort()
    29. End If
    30. End Sub
    31. ' Bei Klick auf den 2. Button, Vorgang abbrechen
    32. Private Sub Button2_Click(ByVal sender As System.Object, _
    33. ByVal e As System.EventArgs) Handles Button2.Click
    34. f.Abort()
    35. End Sub
    36. End Class


    Classe:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class SearchFile
    3. Inherits Object
    4. Private m_FileName As String
    5. Private m_Log As Boolean
    6. Private m_Drives() As String
    7. Private m_sw As IO.StreamWriter
    8. Private m_Abort As Boolean
    9. Public Event CurrentFile(ByVal FileName As String, ByVal IsEqual As Boolean)
    10. ' Vorgang abbrechen
    11. Public Sub Abort()
    12. Me.m_Abort = True
    13. End Sub
    14. ' Klassen-Initialisierung
    15. Public Sub New(ByVal FileName As String, ByVal Drives() As String, ByVal Log As Boolean)
    16. MyBase.New()
    17. Me.m_FileName = FileName
    18. Me.m_Log = Log
    19. Me.m_Drives = Drives
    20. End Sub
    21. ' Suchvorgang starten
    22. Public Sub Search()
    23. Try
    24. Me.m_Abort = False
    25. If Me.m_Log Then m_sw = New IO.StreamWriter("log.txt", False)
    26. For Each d As String In Me.m_Drives
    27. Me.Search(d)
    28. If Me.m_Abort Then Return
    29. Next
    30. Finally
    31. If Not m_sw Is Nothing Then
    32. m_sw.Close()
    33. End If
    34. End Try
    35. End Sub
    36. ' aktuelle Datei in LogFile speichern
    37. Private Sub Log(ByVal CurrentFile As String)
    38. If Not Me.m_Log Then Return
    39. m_sw.WriteLine(CurrentFile)
    40. End Sub
    41. ' Vergleich, ob es sich bei der aktuellen
    42. ' Datei um die gesuchte Datei handelt
    43. Private Sub IsEqual(ByVal CurrentItem As String)
    44. RaiseEvent CurrentFile(CurrentItem, _
    45. Me.m_FileName.ToUpper.Equals(IO.Path.GetFileName(CurrentItem).ToUpper))
    46. End Sub
    47. ' Verzeichnis durchsuchen
    48. Private Sub SearchFile(ByVal Dir As String)
    49. For Each f As String In IO.Directory.GetFiles(Dir)
    50. Me.Log(f)
    51. Me.IsEqual(f)
    52. If Me.m_Abort Then Return
    53. Next
    54. End Sub
    55. ' alle Verzeichnisse ermitteln und Suchvorgang ausführen
    56. Private Sub Search(ByVal Dir As String)
    57. Try
    58. SearchFile(Dir)
    59. For Each d As String In IO.Directory.GetDirectories(Dir)
    60. Try
    61. If Me.m_Abort Then Return
    62. Search(d)
    63. Catch ex As Exception
    64. Debug.WriteLine(ex.Message)
    65. End Try
    66. Next
    67. Catch ex As Exception
    68. Debug.WriteLine(ex.Message)
    69. End Try
    70. End Sub
    71. End Class

    TVX schrieb:

    Alle Platten durchsuchen
    Mit DirectoryInfo.GetFiles(). Entsprechende Maske, entsprechende Einschränkungen beim Pfad und los.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Super das ist wirklich Super zu gebrauchen.
    Ich habe in der Zeit auch noch ein mal geschaut da mir ja gesagt wurde das diese Anwendung keine Pfade in der Registry hinterlassen und ich Anfangs auch nichts gefunden habe, habe ich jetzt noch einmal alles Gründlch durchsucht und aber tatsächlich eine Pfadangabe in der Registry gefunden.
    Der Schlüssel in der Registry sieht wie folgt aus:
    (Standard) - REG_SZ - "D:\MeinOrdner\MeineAnwendungen\Zielordner\Zieldatei.exe" "%1"


    Nun habe ich auch schon versucht diesen Pfad mir einfach in einem TextBlock anzeigen zu lassen was ich aber nicht schaffe. Der TextBlock bleibt Leer.
    Ich weiß auch nicht ob es an dem "(Standard)" liegt denn es gibt keinen anderen Schlüssen.

    Quellcode

    1. Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Classes\Applications\AppFolder\shell\open\command", True)
    2. Dim value As String = CType(key.GetValue("(Standard)"), String)
    3. test.Text = value


    Auch das habe ich versucht:

    Quellcode

    1. Dim path As String
    2. Dim NewKey As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Classes\Applications\AppFolder\shell\open\command", True)
    3. If Not NewKey Is Nothing Then
    4. path = CType(NewKey.GetValue("(Standard)"), String)
    5. test.Text = path
    6. Else
    7. '...
    8. End If

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „StolleJay“ ()

    Wenn das Programm sich auch als COM-Objekt registriert hat, kannst du über den Klassennamen eine Instanz starten und dann anhand des Prozesses die ausführende Datei(über Modules, glaube ich) auslesen.

    EDIT: Ich glaube, der Code war in etwa so: Marshal.CreateComObject("Namespace.Class")

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Higlav“ ()

    'Lesen

    VB.NET-Quellcode

    1. TextBox1.Text = My.Computer.Registry.GetValue("PFAD", "DATEI", Nothing)

    'Prüfen ob vorhanden

    VB.NET-Quellcode

    1. If My.Computer.Registry.GetValue("PFAD", "DATEI", Nothing) Is Nothing Then
    2. MsgBox("Der Schlüssel exsistiert nicht !", MsgBoxStyle.Critical, "(( Kein Key ))")
    3. Else
    4. MsgBox("Der Schlüssel exsistiert !", MsgBoxStyle.Information, "(( Key gefunden ))")
    5. End If