2017-02-28 52 views
10

Próbuję utworzyć skrót (.lnk) w moim systemie plików Windows. Kod, który mam działa, działa prawidłowo. Jednak po uruchomieniu tej samej aplikacji konsolowej na serwerze Windows 2008R2 działa ona inaczej.

Tworzenie skrótu modyfikuje ścieżkę docelową

Więc mam aplikacji konsoli i oto co się dzieje:
Mój program po prostu tworzy skrót na pulpicie z .docx rozszerzenia i wszystko pójdzie dobrze na moim komputerze lokalnym. Gdy uruchomię tę samą aplikację konsoli na moim serwerze, utworzy on ten sam skrót, ale cel został zmodyfikowany ... zmienił obiekt docelowy na plik .doc.

Innymi słowy, kiedy uruchomić aplikację konsoli:

LocalMachine

Tworzy MyWordFile.lnk wskazując U: \ test.docx

Server

Tworzy MyWordFile.lnk wskazując U: \ Test.doc


Jest to dziwne zachowanie. Oto kod

Kod

using System; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Runtime.InteropServices.ComTypes; 
using System.Text; 

namespace TestShortcut 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //ShortcutTarget 
      var sTarget = @"U:\test.docx"; 

      //ShortCutName 
      var sName = @"MyWordFile.lnk"; 

      IShellLink link = (IShellLink)new ShellLink(); 
      link.SetPath(sTarget); 

      IPersistFile file = (IPersistFile)link; 
      string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 
      file.Save(Path.Combine(desktopPath, sName), false); 
     } 
    } 

    [ComImport] 
    [Guid("00021401-0000-0000-C000-000000000046")] 
    internal class ShellLink 
    { 
    } 

    [ComImport] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("000214F9-0000-0000-C000-000000000046")] 
    internal interface IShellLink 
    { 
     void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags); 
     void GetIDList(out IntPtr ppidl); 
     void SetIDList(IntPtr pidl); 
     void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); 
     void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); 
     void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); 
     void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); 
     void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); 
     void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); 
     void GetHotkey(out short pwHotkey); 
     void SetHotkey(short wHotkey); 
     void GetShowCmd(out int piShowCmd); 
     void SetShowCmd(int iShowCmd); 
     void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); 
     void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); 
     void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); 
     void Resolve(IntPtr hwnd, int fFlags); 
     void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); 
    } 
} 



Aktualizacja

Zauważyłem, że 4. charakter zostanie usunięty z rozszerzeniem podsystemu. Tak więc, kiedy mam plik "file.abcdef", link wskazuje na "file.abc". Również obowiązuje zastępowane dla podkreślenia, więc „mój file.abcd” wskaźnik staje się „my_file.abc”

Odpowiedz

6

Tworzenie skrótu nie zmienia nazwę celu.

Widzisz coś innego, "my_file.abc" to short name z "my file.abcd". Takie nazwy są zawsze tworzone w systemie plików, który wciąż ma włączoną funkcję generowania krótkich nazw. Prawie wszystkie z nich wciąż się zdarzają, chociaż dziś jest to bardzo rzadko konieczne. Utrzymywanie "mój plik.abcd" kompatybilny z programami, które mogą obsługiwać tylko nazwy MS-Dos wymaga, aby miejsce zostało zastąpione, a rozszerzenie skrócone do 3 liter. W takich nazwach często widzisz także "~ 1", który służy do skracania nazwy pliku do 8 liter.

Możesz zobaczyć krótkie nazwy z DIR /x.

To, jak dostałeś krótką nazwę tego pliku, nie jest oczywiste z pytania. Ale deklaracja interfejsu IShellLink jest z pewnością błędna, metody nie są wymienione we właściwej kolejności. Ma to bardzo poważne konsekwencje dla interfejsu ComInterfaceType.InterfaceIsIUnknown, w nieodpowiedni sposób wywołasz niewłaściwą metodę. Ustawiciel właściwości Path jest w rzeczywistości drugą metodą. Teraz nazywasz metodę 18., nie jest tak trudno zgadnąć, co może zrobić. Cóż, coś bardzo zaskakującego, jeśli nie wyrzuci wyjątku, to się kwalifikuje :) Nie jest to całkowicie nieprawdopodobne btw, 17. dodaną metodą był getter dla Target property, dodany w późniejszej wersji interfejsu. Możesz przypadkowo uderzyć w nieudokumentowanego setera. Celowo nieudokumentowane.

Po prostu nie deklaruj interfejsu samodzielnie. Najlepszym sposobem na to jest użycie polecenia Projekt> Dodaj odwołanie> przycisk Przeglądaj> wybierz C: \ Windows \ System32 \ Shell32.dll. Opisano bardziej szczegółowo w this post.

+0

Dziękuję bardzo, bardzo jasne wyjaśnienie! –