总结:我搜索了MSDN,并考虑创建自己的SetValue
,但我无法找到它的任何源代码。它不在DLL中,就像InitPropVariantFromString
一样,它在头文件中,但我无法找到它。 :(如果你可以请告诉我htat C ++代码我将从那里接受它:)
最重要的是展示我付出的努力。
这是我转换的微小C ++代码:
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
IPropertyStore *pps;
HRESULT hr = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pps));
if (SUCCEEDED(hr)) {
IPropertyStore_SetValue(pps, PKEY_AppUserModel_ID, L"Contoso.Scratch");
}
}
我已将其翻译为:
var ppv = ctypes.voidptr_t(0);
var pps = new IID();
var HR_pps = CLSIDFromString('{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', pps.address());
if (!checkHRESULT(HR_pps)) { throw new Error('checkHRESULT error'); }
var hr = SHGetPropertyStoreForWindow(hwnd, pps.address(), ppv.address());
if (!checkHRESULT(hr)) { throw new Error('checkHRESULT error'); }
var pszValue = ctypes.jschar.array()('Contoso.Scratch'); // PCWSTR
IPropertyStore_SetValue(pps.address(), PKEY_AppUserModel_ID, pszValue.address());
我从这个C ++中转换了IPropertyStore_SetValue
:
HRESULT IPropertyStore_SetValue(IPropertyStore *pps, REFPROPERTYKEY pkey, PCWSTR pszValue)
{
PROPVARIANT var;
HRESULT hr = InitPropVariantFromString(pszValue, &var);
if (SUCCEEDED(hr)) {
hr = pps->SetValue(pkey, var);
PropVariantClear(&var);
}
return hr;
}
我明白了:
var struct_PROPVARIANT = ctypes.StructType('PROPVARIANT', [
{'fntud': struct_GUID}, // GUID
{'pid': ctypes.unsigned_long}, // DWORD
// comment from loomo on union :: union not supported by js-ctypes https://bugzilla.mozilla.org/show_bug.cgi?id=535378 "You can always typecast pointers, at least as long as you know which type is the biggest"
// so now in my case i know that InitPropVariantFromString is looking to se the pwszVal so forget all the other crap in the union and just leave this one
{'pwszVal': new ctypes.PointerType(ctypes.jschar)} // LPWSTR
]);
var IPropertyStore_SetValue = function(pps /** IPopertyStore pointer **/, pkey /** PROPERTYKEY **/, pszValue /** PCWSTR **/) {
var v = new struct_PROPVARIANT(); // PROPVARIANT
var rez = InitPropVariantFromString(pszValue, v.address());
if (rez) {
console.info('pps.SetValue', pps.SetValue);
pps.SetValue(pkey, v);
} else {
throw new Error('failed InitPropVariantFromString');
}
return true;
}
所以这要求我写InitPropVariantFromString
我做了:
function InitPropVariantFromString(string /** PCWSTR **/, propvarPtr /** PROPVARIANT pointer **/) {
var hr = SHStrDup(string, propvarPtr.contents.pwszVal.address());
if (!checkHRESULT(hr)) {
//PropVariantInit(propvarPtr); //can skip this, it just does a memset
}
return true;
}
我的SHSTRDUP DILEMMA上的一个小小的问题(这个问题只是表明我努力工作并且无法解释的奇怪现象让它发挥作用)
所以这要求我做
SHStrDup
,我认为这需要两个ctypes.jschar.ptr
的参数,因为它是LPCTSTR
的第一个参数 和LPTSTR
的第二个arg。对于第一个论点,我正在通过召回的PCWSTR
ctypes.jschar.array()('Contoso.Scratch')
。所以,当我第一次arg 定义设置为ctypes.jschar.ptr
它将无法使用它抛出 此错误:expected type pointer, got ctypes.jschar.array(16).ptr(ctypes.UInt64("0x2855b560"))
所以我将定义从
ctypes.jschar.ptr
改为 确定ctypes.voidptr_t
所以它适用于这个论点 但随后在第二个参数上抛出错误回忆起propvarPtr.contents.pwszVal.address()
:
ctypes.jschar.ptr.ptr(ctypes.UInt64("0x20fdb3b4"))
,然后我最终设置了
SHStrDup
的两个参数ctypes.voidptr_t
并且它有效。不知道为什么但它有效。和propvarPtr.contents.pwszVal
肯定会被填充,因为 当我在console.log时显示:"propvarPtr.contents.pwszVal" CData { contents: "C" }
。所以最终的
SHStrDup
定义看起来像这样:/* http://msdn.microsoft.com/en-us/library/windows/desktop/bb759924%28v=vs.85%29.aspx * HRESULT SHStrDup( * __in_ LPCTSTR pszSource, * __out_ LPTSTR *ppwsz * ); */ var SHStrDup = shlwapi.declare('SHStrDupW', ctypes.winapi_abi, ctypes.long, // HRESULT ctypes.voidptr_t, // LPCTSTR // should be ctypes.jschar.ptr OR ctypes.char.ptr // im trying to pass PCWSTR here, which is `ctypes.jschar.array()('blah blah').address()` ctypes.voidptr_t // LPTSTR // should be ctypes.jschar.ptr OR ctypes.char.ptr // im trying to pass address to struct_PROPVARIANT.pwszVal which is new ctypes.PointerType(ctypes.jschar) );
所以现在所有这一切都过去了,我最终回到了IPropertyStore_SetValue
,如果:
var rez = InitPropVariantFromString(pszValue, v.address());
if (rez) {
console.info('pps.SetValue', pps.SetValue);
pps.SetValue(pkey, v);
} else {
throw new Error('failed InitPropVariantFromString');
}
现在rez
是真的,所以它现在尝试pps.SetValue
,这就是kaput的地方,我无法弄清楚如何修复它。 :(
我搜索了MSDN,并考虑创建自己的SetValue
,但我无法找到它的任何源代码。它不在DLL中,就像InitPropVariantFromString
一样,它在头文件中,但我无法找到它。 :(如果你可以请告诉我htat C ++代码我将从那里接受它:)
答案 0 :(得分:0)
解决了,我不得不使用VTBL:https://github.com/Noitidart/_scratchpad/blob/master/IPropertyStore%20COM%20jsctypes.js
Vtbl
问题中的定义顺序很重要。因此,如果您想对Vtbl
s
var IPropertyStoreVtbl = new ctypes.StructType('IPropertyStoreVtbl');
var IPropertyStore = new ctypes.StructType('IPropertyStore', [{
'lpVtbl': IPropertyStoreVtbl.ptr
}]);
this.IPropertyStorePtr = new ctypes.PointerType(IPropertyStore);
IPropertyStoreVtbl.define(
[{ //start inherit from IUnknown
'QueryInterface': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr,
this.REFIID, // riid
this.VOIDPTR // **ppvObject
]).ptr
}, {
'AddRef': ctypes.FunctionType(ctypes.stdcall_abi,
this.ULONG, [
IPropertyStore.ptr
]).ptr
}, {
'Release': ctypes.FunctionType(ctypes.stdcall_abi,
this.ULONG, [
IPropertyStore.ptr
]).ptr
}, { //end inherit from IUnknown //start IPropertyStore
'GetCount': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr,
this.DWORD.ptr // *cProps
]).ptr
}, {
'GetAt': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr,
this.DWORD, // iProp
this.PROPERTYKEY.ptr //*pkey
]).ptr
}, {
'GetValue': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr,
this.REFPROPERTYKEY, // key
this.PROPVARIANT.ptr // *pv
]).ptr
}, {
'SetValue': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr,
this.REFPROPERTYKEY, // key
this.REFPROPVARIANT // propvar
]).ptr
}, {
'Commit': ctypes.FunctionType(ctypes.stdcall_abi,
this.HRESULT, [
IPropertyStore.ptr
]).ptr
}]
);
然后获取窗口的IPropertyStore
:
var ppsPtr = new ostypes.IPropertyStorePtr();
var hr_SHGetPropertyStoreForWindow = _dec('SHGetPropertyStoreForWindow')(cHwnd, IID_IPropertyStore.address(), ppsPtr.address());
checkHRESULT(hr_SHGetPropertyStoreForWindow, 'SHGetPropertyStoreForWindow');
var pps = ppsPtr.contents.lpVtbl.contents;
现在您可以使用IPropertyStore :: SetValue
和IPropertyStore :: Release
但请确保将ppsPtr
作为第一个参数传递给他们,然后剩下的参数就是您所期望的:var hr = pps.SetValue(ppsPtr, firstArgOf_SetValue, secondArgOf_SetValue)
< / p>
从暂存器添加复制粘贴可运行脚本。 复制并粘贴:http://pastebin.mozilla.org/8429999
这将相当于此XPCOM:
var win = Services.wm.getMostRecentWindow(null);
Cc["@mozilla.org/windows-taskbar;1"].getService(Ci.nsIWinTaskbar).setGroupIdForWindow(win, 'Contoso.Scratch')
是的,它的长期但好处是,没有XPCOM来设置RelaunchCommand
和RelaunchIconResource
等等。这就是为什么需要js-ctypes。