【问题标题】:GetShortPathNameA not working in C#GetShortPathNameA 在 C# 中不起作用
【发布时间】:2010-04-06 13:34:15
【问题描述】:

我正在尝试从长文件名中获取短文件名,但我在 c# 代码中遇到问题。 VB.Net代码为:

Declare Function GetShortPathName Lib "kernel32" _
    Alias "GetShortPathNameA" (ByVal lpszLongPath As String, _
    ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long

Public Function GetShortName(ByVal sLongFileName As String) As String
    Dim lRetVal As Long, sShortPathName As String, iLen As Integer
    'Set up buffer area for API function call return
    sShortPathName = Space(255)
    iLen = Len(sShortPathName)

    'Call the function
    lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen)
    'Strip away unwanted characters.
     GetShortName = Left(sShortPathName, lRetVal)
End Function

我已将此函数转换为 c#:

[DllImport("kernel32", EntryPoint = "GetShortPathNameA")]
static extern long GetShortPathName(string lpszLongPath, string lpszShortPath, long cchBuffer);

public string GetShortName(string sLongFileName)
{
    long lRetVal;
    string sShortPathName;
    int iLen;

    // Set up buffer area for API function call return
    sShortPathName = new String(' ', 1024);
    iLen = sShortPathName.Length;

    // Call the function
    lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen);

    // Strip away unwanted characters.
    return sShortPathName.Trim();
}

但我无法让 c# 版本工作。我错过了什么或有什么问题吗?

【问题讨论】:

    标签: c# .net windows vb.net winapi


    【解决方案1】:

    VB 声明可以追溯到 VB6,它对于 .NET 语言是非常不合适的。尽管 P/Invoke marshaller 将允许将非托管代码写入字符串,但由于字符串暂留,它会导致随机失败。您还真的想要使用 Unicode 版本,这样您就不会得到意外的字符翻译。如果功能失败,您想做一些有意义的事情。这是我的版本:

    public static string GetShortName(string sLongFileName) {
      var buffer = new StringBuilder(259);
      int len = GetShortPathName(sLongFileName, buffer, buffer.Capacity);
      if (len == 0) throw new System.ComponentModel.Win32Exception();
      return buffer.ToString();
    }
    
    [DllImport("kernel32", EntryPoint = "GetShortPathName", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int GetShortPathName(string longPath, StringBuilder shortPath, int bufSize);
    

    【讨论】:

      【解决方案2】:

      也许是因为 CharSet/Marshaling,请记住字符串是不可变的。请尝试以下操作:

      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError=true)]
      static extern uint GetShortPathName(
         [MarshalAs(UnmanagedType.LPTStr)]
         string lpszLongPath,
         [MarshalAs(UnmanagedType.LPTStr)]
         StringBuilder lpszShortPath,
         uint cchBuffer);
      

      (来自pinvoke

      /// <summary>
      /// The ToLongPathNameToShortPathName function retrieves the short path form of a specified long input path
      /// </summary>
      /// <param name="longName">The long name path</param>
      /// <returns>A short name path string</returns>
      public static string ToShortPathName(string longName)
      {
          uint bufferSize = 256;
      
          // don´t allocate stringbuilder here but outside of the function for fast access
          StringBuilder shortNameBuffer = new StringBuilder((int)bufferSize);
      
          uint result = GetShortPathName(longName, shortNameBuffer, bufferSize);
      
          return shortNameBuffer.ToString();
      }
      

      【讨论】:

        【解决方案3】:

        pinvoke.net 在以下位置列出导入:

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError=true)]
        static extern uint GetShortPathName(
           [MarshalAs(UnmanagedType.LPTStr)]
           string lpszLongPath,
           [MarshalAs(UnmanagedType.LPTStr)]
           StringBuilder lpszShortPath,
           uint cchBuffer);
        

        pinvoke.net 是解决此类问题的一个很好的参考,您不确定签名的翻译方式。

        这会像这样改变你的代码:

        public static string GetShortName(string sLongFileName)
        {
            long lRetVal;
            int iLen = 1024;
            StringBuilder sShortPathName = new StringBuilder(iLen);
        
            // Call the function
            lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen);
        
            // Strip away unwanted characters.
            return sShortPathName.ToString();
        }
        

        【讨论】:

        • 在 Windows 10 中 iLen 必须是 uint,除了:非常感谢!
        猜你喜欢
        • 1970-01-01
        • 2011-06-03
        • 1970-01-01
        • 2021-08-04
        • 2015-09-08
        • 2014-04-29
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多