Win32 API 日本語リファレンス
ホームStorage.FileSystem › GetShortPathNameW

GetShortPathNameW

関数
長い形式のパスを8.3形式の短いパスに変換する。
DLLKERNEL32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// KERNEL32.dll  (Unicode / -W)
#include <windows.h>

DWORD GetShortPathNameW(
    LPCWSTR lpszLongPath,
    LPWSTR lpszShortPath,   // optional
    DWORD cchBuffer
);

パラメーター

名前方向説明
lpszLongPathLPCWSTRin

パス文字列です。

既定では、名前は MAX_PATH 文字に制限されます。この制限を 32,767 ワイド文字に拡張するには、パスの先頭に "\\?\" を付加します。詳細については、「ファイル、パス、および名前空間の命名」を参照してください。

ヒント

Windows 10 バージョン 1607 以降では、"\\?\" を付加せずに MAX_PATH 制限を解除するようオプトインできます。詳細については、「ファイル、パス、および名前空間の命名」の「Maximum Path Length Limitation」セクションを参照してください。

lpszShortPathLPWSTRoutoptional

lpszLongPath で指定したパスの、null 終端された短い形式を受け取るバッファーへのポインターです。

このパラメーターに NULL を、cchBuffer に 0 を渡すと、指定した lpszLongPath に必要なバッファーサイズが常に返されます。

cchBufferDWORDin

lpszShortPath が指す バッファーのサイズ(TCHAR 単位)です。

lpszShortPathNULL に設定する場合は、このパラメーターを 0 に設定します。

戻り値の型: DWORD

公式ドキュメント

指定したパスの短いパス形式を取得します。(GetShortPathNameW)

戻り値

関数が成功した場合、戻り値は lpszShortPath にコピーされた文字列の長さ(TCHAR 単位)で、 終端の null 文字は含みません。

lpszShortPath バッファーがパスを格納するには小さすぎる場合、戻り値は パスと終端の null 文字を格納するために必要なバッファーのサイズ(TCHAR 単位)です。

その他の理由で関数が失敗した場合、戻り値は 0 です。拡張エラー情報を取得するには、 GetLastError を呼び出します。

解説(Remarks)

lpszLongPath パラメーターで指定するパスは、完全なパスや 長いパスである必要はありません。短い形式が、指定したパスより長くなる場合もあります。

戻り値が cchBuffer パラメーターで指定した値より大きい場合は、 パスを格納するのに十分な大きさのバッファーを用意して関数を再度呼び出すことができます。この場合の例と、動的割り当てのために長さ 0 のバッファーを使用する方法については、Example Code セクションを参照してください。

注意 この場合の戻り値には終端の null 文字を含む長さが含まれますが、 成功時の戻り値にはカウントに終端の null 文字が含まれません。
指定したパスが既に短い形式であり変換が不要な場合、関数は 指定したパスを lpszShortPath パラメーターで指定したバッファーに単にコピーします。

lpszShortPath パラメーターには lpszLongPath パラメーターと同じ値を設定できます。つまり、短いパス用の出力バッファーを 入力パス文字列のアドレスに設定できます。その場合は、cchBuffer パラメーターが このバッファーの合計サイズ(TCHAR 単位)を正確に表していることを常に確認してください。

ファイルの長い名前は、短い名前から GetLongPathName 関数を呼び出して取得できます。あるいは、 GetLongPathName が利用できない場合は、パスの各構成要素に対して FindFirstFile を呼び出して、 対応する長い名前を取得できます。

ファイルまたはディレクトリにはアクセスできるが、そのファイルまたはディレクトリの一部の親ディレクトリには アクセスできない場合があります。その結果、GetShortPathName は あるパス構成要素の親ディレクトリを照会してその構成要素の短い名前を判別できないときに失敗することがあります。このチェックは、既に短い名前の要件を満たしているディレクトリ構成要素についてはスキップできます。 詳細については、 ファイル、パス、および名前空間の命名Short vs. Long Names セクションを参照してください。

Windows 8 および Windows Server 2012 では、この関数は次の技術でサポートされています。

技術 サポート
Server Message Block (SMB) 3.0 プロトコル はい
SMB 3.0 Transparent Failover (TFO) いいえ
SMB 3.0 with Scale-out File Shares (SO) いいえ
Cluster Shared Volume File System (CsvFS) いいえ
Resilient File System (ReFS) はい

SMB 3.0 は、継続的可用性機能を持つ共有上の短い名前をサポートしません。

Resilient File System (ReFS) は短い名前をサポートしません。ディスク上に短い名前を持たないパスに対して GetShortPathName を呼び出すと、呼び出しは成功しますが、代わりに長い名前のパスが返されます。この結果は NTFS ボリュームでも起こり得ます。これは、特定の長い名前に対して短い名前が存在する保証がないためです。

GetShortPathName を使用する例については、 GetFullPathName の Example Code セクションを参照してください。

次の C++ の例は、動的に割り当てた出力バッファーの使用方法を示します。
//...
    long     length = 0;
    TCHAR*   buffer = NULL;

// First obtain the size needed by passing NULL and 0.

    length = GetShortPathName(lpszPath, NULL, 0);
    if (length == 0) ErrorExit(TEXT("GetShortPathName"));

// Dynamically allocate the correct size 
// (terminating null char was included in length)

    buffer = new TCHAR[length];

// Now simply call again using same long path.

    length = GetShortPathName(lpszPath, buffer, length);
    if (length == 0) ErrorExit(TEXT("GetShortPathName"));

    _tprintf(TEXT("long name = %s shortname = %s"), lpszPath, buffer);
    
    delete [] buffer;
///...
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// KERNEL32.dll  (Unicode / -W)
#include <windows.h>

DWORD GetShortPathNameW(
    LPCWSTR lpszLongPath,
    LPWSTR lpszShortPath,   // optional
    DWORD cchBuffer
);
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern uint GetShortPathNameW(
    [MarshalAs(UnmanagedType.LPWStr)] string lpszLongPath,   // LPCWSTR
    [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpszShortPath,   // LPWSTR optional, out
    uint cchBuffer   // DWORD
);
<DllImport("KERNEL32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function GetShortPathNameW(
    <MarshalAs(UnmanagedType.LPWStr)> lpszLongPath As String,   ' LPCWSTR
    <MarshalAs(UnmanagedType.LPWStr)> lpszShortPath As System.Text.StringBuilder,   ' LPWSTR optional, out
    cchBuffer As UInteger   ' DWORD
) As UInteger
End Function
' lpszLongPath : LPCWSTR
' lpszShortPath : LPWSTR optional, out
' cchBuffer : DWORD
Declare PtrSafe Function GetShortPathNameW Lib "kernel32" ( _
    ByVal lpszLongPath As LongPtr, _
    ByVal lpszShortPath As LongPtr, _
    ByVal cchBuffer As Long) As Long
' Unicode(W): 文字列は ByVal As LongPtr とし StrPtr(unicodeStr) を渡す
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
GetShortPathNameW.restype = wintypes.DWORD
GetShortPathNameW.argtypes = [
    wintypes.LPCWSTR,  # lpszLongPath : LPCWSTR
    wintypes.LPWSTR,  # lpszShortPath : LPWSTR optional, out
    wintypes.DWORD,  # cchBuffer : DWORD
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
GetShortPathNameW = Fiddle::Function.new(
  lib['GetShortPathNameW'],
  [
    Fiddle::TYPE_VOIDP,  # lpszLongPath : LPCWSTR
    Fiddle::TYPE_VOIDP,  # lpszShortPath : LPWSTR optional, out
    -Fiddle::TYPE_INT,  # cchBuffer : DWORD
  ],
  -Fiddle::TYPE_INT)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"
#[link(name = "kernel32")]
extern "system" {
    fn GetShortPathNameW(
        lpszLongPath: *const u16,  // LPCWSTR
        lpszShortPath: *mut u16,  // LPWSTR optional, out
        cchBuffer: u32  // DWORD
    ) -> u32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern uint GetShortPathNameW([MarshalAs(UnmanagedType.LPWStr)] string lpszLongPath, [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpszShortPath, uint cchBuffer);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_GetShortPathNameW' -Namespace Win32 -PassThru
# $api::GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
#uselib "KERNEL32.dll"
#func global GetShortPathNameW "GetShortPathNameW" wptr, wptr, wptr
; GetShortPathNameW lpszLongPath, varptr(lpszShortPath), cchBuffer   ; 戻り値は stat
; lpszLongPath : LPCWSTR -> "wptr"
; lpszShortPath : LPWSTR optional, out -> "wptr"
; cchBuffer : DWORD -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "KERNEL32.dll"
#cfunc global GetShortPathNameW "GetShortPathNameW" wstr, var, int
; res = GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
; lpszLongPath : LPCWSTR -> "wstr"
; lpszShortPath : LPWSTR optional, out -> "var"
; cchBuffer : DWORD -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; DWORD GetShortPathNameW(LPCWSTR lpszLongPath, LPWSTR lpszShortPath, DWORD cchBuffer)
#uselib "KERNEL32.dll"
#cfunc global GetShortPathNameW "GetShortPathNameW" wstr, var, int
; res = GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
; lpszLongPath : LPCWSTR -> "wstr"
; lpszShortPath : LPWSTR optional, out -> "var"
; cchBuffer : DWORD -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procGetShortPathNameW = kernel32.NewProc("GetShortPathNameW")
)

// lpszLongPath (LPCWSTR), lpszShortPath (LPWSTR optional, out), cchBuffer (DWORD)
r1, _, err := procGetShortPathNameW.Call(
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpszLongPath))),
	uintptr(lpszShortPath),
	uintptr(cchBuffer),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // DWORD
function GetShortPathNameW(
  lpszLongPath: PWideChar;   // LPCWSTR
  lpszShortPath: PWideChar;   // LPWSTR optional, out
  cchBuffer: DWORD   // DWORD
): DWORD; stdcall;
  external 'KERNEL32.dll' name 'GetShortPathNameW';
result := DllCall("KERNEL32\GetShortPathNameW"
    , "WStr", lpszLongPath   ; LPCWSTR
    , "Ptr", lpszShortPath   ; LPWSTR optional, out
    , "UInt", cchBuffer   ; DWORD
    , "UInt")   ; return: DWORD
●GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer) = DLL("KERNEL32.dll", "dword GetShortPathNameW(char*, char*, dword)")
# 呼び出し: GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
# lpszLongPath : LPCWSTR -> "char*"
# lpszShortPath : LPWSTR optional, out -> "char*"
# cchBuffer : DWORD -> "dword"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。
const std = @import("std");

extern "kernel32" fn GetShortPathNameW(
    lpszLongPath: [*c]const u16, // LPCWSTR
    lpszShortPath: [*c]u16, // LPWSTR optional, out
    cchBuffer: u32 // DWORD
) callconv(std.os.windows.WINAPI) u32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc GetShortPathNameW(
    lpszLongPath: WideCString,  # LPCWSTR
    lpszShortPath: ptr uint16,  # LPWSTR optional, out
    cchBuffer: uint32  # DWORD
): uint32 {.importc: "GetShortPathNameW", stdcall, dynlib: "KERNEL32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "kernel32");
extern(Windows)
uint GetShortPathNameW(
    const(wchar)* lpszLongPath,   // LPCWSTR
    wchar* lpszShortPath,   // LPWSTR optional, out
    uint cchBuffer   // DWORD
);
ccall((:GetShortPathNameW, "KERNEL32.dll"), stdcall, UInt32,
      (Cwstring, Ptr{UInt16}, UInt32),
      lpszLongPath, lpszShortPath, cchBuffer)
# lpszLongPath : LPCWSTR -> Cwstring
# lpszShortPath : LPWSTR optional, out -> Ptr{UInt16}
# cchBuffer : DWORD -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
uint32_t GetShortPathNameW(
    const uint16_t* lpszLongPath,
    uint16_t* lpszShortPath,
    uint32_t cchBuffer);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
-- lpszLongPath : LPCWSTR
-- lpszShortPath : LPWSTR optional, out
-- cchBuffer : DWORD
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
-- Unicode(-W): uint16_t* には UTF-16LE のバッファ(ffi.new("uint16_t[?]", ...))を渡す。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const GetShortPathNameW = lib.func('__stdcall', 'GetShortPathNameW', 'uint32_t', ['str16', 'uint16_t *', 'uint32_t']);
// GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
// lpszLongPath : LPCWSTR -> 'str16'
// lpszShortPath : LPWSTR optional, out -> 'uint16_t *'
// cchBuffer : DWORD -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  GetShortPathNameW: { parameters: ["buffer", "buffer", "u32"], result: "u32" },
});
// lib.symbols.GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer)
// lpszLongPath : LPCWSTR -> "buffer"
// lpszShortPath : LPWSTR optional, out -> "buffer"
// cchBuffer : DWORD -> "u32"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
uint32_t GetShortPathNameW(
    const uint16_t* lpszLongPath,
    uint16_t* lpszShortPath,
    uint32_t cchBuffer);
C, "KERNEL32.dll");
// $ffi->GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer);
// lpszLongPath : LPCWSTR
// lpszShortPath : LPWSTR optional, out
// cchBuffer : DWORD
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
    int GetShortPathNameW(
        WString lpszLongPath,   // LPCWSTR
        char[] lpszShortPath,   // LPWSTR optional, out
        int cchBuffer   // DWORD
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("kernel32")]
lib LibKERNEL32
  fun GetShortPathNameW = GetShortPathNameW(
    lpszLongPath : UInt16*,   # LPCWSTR
    lpszShortPath : UInt16*,   # LPWSTR optional, out
    cchBuffer : UInt32   # DWORD
  ) : UInt32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef GetShortPathNameWNative = Uint32 Function(Pointer<Utf16>, Pointer<Utf16>, Uint32);
typedef GetShortPathNameWDart = int Function(Pointer<Utf16>, Pointer<Utf16>, int);
final GetShortPathNameW = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<GetShortPathNameWNative, GetShortPathNameWDart>('GetShortPathNameW');
// lpszLongPath : LPCWSTR -> Pointer<Utf16>
// lpszShortPath : LPWSTR optional, out -> Pointer<Utf16>
// cchBuffer : DWORD -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function GetShortPathNameW(
  lpszLongPath: PWideChar;   // LPCWSTR
  lpszShortPath: PWideChar;   // LPWSTR optional, out
  cchBuffer: DWORD   // DWORD
): DWORD; stdcall;
  external 'KERNEL32.dll' name 'GetShortPathNameW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "GetShortPathNameW"
  c_GetShortPathNameW :: CWString -> CWString -> Word32 -> IO Word32
-- lpszLongPath : LPCWSTR -> CWString
-- lpszShortPath : LPWSTR optional, out -> CWString
-- cchBuffer : DWORD -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getshortpathnamew =
  foreign "GetShortPathNameW"
    ((ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> returning uint32_t)
(* lpszLongPath : LPCWSTR -> (ptr uint16_t) *)
(* lpszShortPath : LPWSTR optional, out -> (ptr uint16_t) *)
(* cchBuffer : DWORD -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("GetShortPathNameW" get-short-path-name-w :convention :stdcall) :uint32
  (lpsz-long-path (:string :encoding :utf-16le))   ; LPCWSTR
  (lpsz-short-path :pointer)   ; LPWSTR optional, out
  (cch-buffer :uint32))   ; DWORD
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $GetShortPathNameW = Win32::API::More->new('KERNEL32',
    'DWORD GetShortPathNameW(LPCWSTR lpszLongPath, LPWSTR lpszShortPath, DWORD cchBuffer)');
# my $ret = $GetShortPathNameW->Call($lpszLongPath, $lpszShortPath, $cchBuffer);
# lpszLongPath : LPCWSTR -> LPCWSTR
# lpszShortPath : LPWSTR optional, out -> LPWSTR
# cchBuffer : DWORD -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い
公式の関連項目