拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 SHChangeNotify不更新URL=更改我的.url快捷方式档案

SHChangeNotify不更新URL=更改我的.url快捷方式档案

白鹭 - 2022-02-16 2103 0 0

我有一个简单的 Delphi 应用程序,可以为 URL 创建桌面快捷方式。.url在用户的桌面档案夹中创建一个带有档案扩展名的两行文本档案

[InternetShortcut]
URL=http://127.0.0.1/admin

这很好用。当我需要使用新 URL 更新档案时,我会覆写旧档案。但是在我重新启动资源管理器或重新启动之前,Windows 不会识别更改。所以我SHChangeNotify()在覆写档案后了解并呼叫了它:

SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH or SHCNF_FLUSH, PChar(Path), nil);

但它没有效果:

  • 我试过有没有SHCNF_FLUSH国旗;
  • SHCNF_FLUSHNOWAIT标志没什么区别。
  • 我也尝试先洗掉档案,然后使用SHCNE_DELETE事件,然后重新创建档案。这也不起作用,它只是继续使用旧的 URL。

如何强制资源管理器在不重新启动的情况下从档案重新加载 URL?

uj5u.com热心网友回复:

虽然档案的内容可以像任何 INI 档案一样对待,但我还没有找到一种直接的方法来控制对它的操作:

  • 当创建一个档案时,它的内容按预期读取:系统默认的URL='s 协议应用程序被启动(即http它很可能是互联网浏览器)。
  • 修改每个档案系统的档案没有任何影响 - MSIE 本身维护快取或 COM 的魔法。

可以通过以下方式间接操作:

  1. 清空档案的现有内容。为什么?因为后面的步骤只会URL=再次添加具有的相同 INI 部分,但第一个部分的URL=值仍然是被考虑的那个。
  2. 访问每个 COM 的档案并更改其属性。可悲的是,这会在档案中写入更多内容 - 在我的情况下,结果/档案的内容是:

但是,它“有效”如下:更改(说:不同的 URL)被识别。把它放在一起,我在 Windows 7 上的 Delphi 7 的以下代码也应该对你有用 - 只需呼叫函式:

uses
  ShlObj, ActiveX, ComObj;

const
  SID_IUniformResourceLocatorA= '{FBF23B80-E3F0-101B-8488-00AA003E56F8}';
  SID_IUniformResourceLocatorW= '{CABB0DA0-DA57-11CF-9974-0020AFD79762}';
  SID_InternetShortcut= '{FBF23B40-E3F0-101B-8488-00AA003E56F8}';

type
  PUrlInvokeCommandInfoA= ^TUrlInvokeCommandInfoA;
  TUrlInvokeCommandInfoA= record
    dwcbSize,
    dwFlags: DWORD;  // Bit field of IURL_INVOKECOMMAND_FLAGS
    hwndParent: HWND;  // Parent window. Valid only if IURL_INVOKECOMMAND_FL_ALLOW_UI is set.
    pcszVerb: LPCSTR;  // Verb to invoke. Ignored if IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB is set.
  end;

  PUrlInvokeCommandInfoW= ^TUrlInvokeCommandInfoW;
  TUrlInvokeCommandInfoW= record
    dwcbSize,
    dwFlags: DWORD;
    hwndParent: HWND;
    pcszVerb: LPCWSTR;
  end;

  IUniformResourceLocatorA= interface( IUnknown )
    [SID_IUniformResourceLocatorA]
    function SetURL( pcszURL: LPCSTR; dwInFlags: DWORD ): HRESULT; stdcall;
    function GetURL( ppszURL: LPSTR ): HRESULT; stdcall;
    function InvokeCommand( purlici: PUrlInvokeCommandInfoA ): HRESULT; stdcall;

  end;

  IUniformResourceLocatorW= interface( IUnknown )
    [SID_IUniformResourceLocatorW]
    function SetURL( pcszURL: LPCWSTR; dwInFlags: DWORD ): HRESULT; stdcall;
    function GetURL( ppszURL: LPWSTR ): HRESULT; stdcall;
    function InvokeCommand(purlici: PUrlInvokeCommandInfoW ): HRESULT; stdcall;
  end;

function SetURL( sFile, sUrl: Widestring ): Integer;
const
  CLSID_InternetShortCut: TGUID= SID_InternetShortcut;
var
  oUrl: IUniformResourceLocatorW;
  oFile: IPersistFile;
  hFile: THandle;
begin
  // First, the existing file's content should be emptied
  hFile:= CreateFileW( PWideChar(sFile), GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0 );
  if hFile= INVALID_HANDLE_VALUE then begin
    result:= 1;  // File might not exist, sharing violation, etc.
    exit;
  end;

  // Initial file pointer is at position 0
  if not SetEndOfFile( hFile ) then begin
    result:= 2;  // Missing permissions, etc.
    CloseHandle( hFile );
    exit;
  end;

  // Gracefully end accessing the file
  if not CloseHandle( hFile ) then begin
    result:= 3;  // File system crashed, etc.
    exit;
  end;

  // Using COM to access properties
  result:= 0;
  try
    oUrl:= CreateComObject( CLSID_InternetShortCut ) as IUniformResourceLocatorW;
  except
    result:= 4;  // CLSID unsupported, COM not available, etc.
  end;
  if result<> 0 then exit;

  // Opening the file again
  oFile:= oUrl as IPersistFile;
  if oFile.Load( PWideChar(sFile), STGM_READWRITE )<> S_OK then begin
    result:= 5;  // Sharing violations, access permissions, etc.
    exit;
  end;

  // Set the property as per interface - only saving the file is not enough
  if oUrl.SetURL( PWideChar(sUrl), 0 )<> S_OK then begin
    result:= 6;
    exit;
  end;

  // Storing the file's new content - setting only the property is not enough
  if oFile.Save( PWideChar(sFile), TRUE )<> S_OK then begin
    result:= 7;
    exit;
  end;

  // Success!
  result:= 0;
end;

根据我的桌面防火墻,执行程序会修改explorer.exeon的存储器IPersistFile.Save()- 在执行 URL 档案之后应该反映其新内容,而在此之前的任何尝试仍然应该对旧档案的内容起作用。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *