From taras.ciuriak at gmail.com Wed Apr 5 08:47:44 2023 From: taras.ciuriak at gmail.com (Taras CIURIAK) Date: Wed, 5 Apr 2023 13:47:44 +0100 Subject: [python-win32] Licensing status? Message-ID: Hi, can anyone please confirm the licensing status of the PyWin32 module? I'm under the impression that it's using the Python Software Foundation License, as that's what it states on the Project page, however I'm getting pushback from the powers that be because there's no clearly obvious License.txt in the source: *"unfortunately I do not believe the Python Software Foundation License is still valid for this package. While in https://pypi.org/project/pywin32/#description it does appear that it is licensed under a Python Software Foundation license, the license has unfortunately may have not (sic) been renewed for quite some time and is not available on github."* Thanks for any assistance you can provide to clarify..../Taras -------------- next part -------------- An HTML attachment was scrubbed... URL: From skippy.hammond at gmail.com Wed Apr 5 19:26:13 2023 From: skippy.hammond at gmail.com (Mark Hammond) Date: Thu, 6 Apr 2023 09:26:13 +1000 Subject: [python-win32] Licensing status? In-Reply-To: References: Message-ID: <010cb21b-fab4-368d-12a1-f1cbdd127509@gmail.com> There are various LICENCE.txt files in subdirectories, which are canonical. These LICENCE.txt files pre-date the PSF licence (or the PSF!) even existing and this package has many many contributors from this week back to last century, so re-licensing is almost impossible. I don't think the PSF licence makes sense for projects not released by the PSF - the closest would be a new custom license exactly like the PSF license, but with some words change to make it clear the PSF isn't releasing it. If your lawyers aren't happy with the situation I'd love to hear their advice for how it could be cleaned up. Cheers, Mark On 5/04/2023 10:47 pm, Taras CIURIAK wrote: > Hi, can anyone please confirm the licensing status of the PyWin32 > module?? I'm under the impression that it's using the Python Software > Foundation License, as that's what it states on the Project page, > however I'm getting pushback from the powers that be because there's no > clearly obvious License.txt in the source: > > /"unfortunately I do not believe the Python Software Foundation License > is still valid for this package. While in > https://pypi.org/project/pywin32/#description > it does appear that it > is licensed under a Python Software Foundation license, the license has > unfortunately may have not?(sic) been renewed for quite some time and is > not available on github."/ > / > / > Thanks for any assistance you can provide to clarify..../Taras > > _______________________________________________ > python-win32 mailing list > python-win32 at python.org > https://mail.python.org/mailman/listinfo/python-win32 From heytrw at gmail.com Sun Apr 9 13:17:07 2023 From: heytrw at gmail.com (Tommy Weber) Date: Sun, 9 Apr 2023 11:17:07 -0600 Subject: [python-win32] Accessing Documentation Through Command Prompt / Help File Message-ID: <251460BF-2E36-4919-9450-6A537E8E9B01@hxcore.ol> An HTML attachment was scrubbed... URL: From steven at manross.net Mon Apr 10 10:41:49 2023 From: steven at manross.net (Steven Manross) Date: Mon, 10 Apr 2023 14:41:49 +0000 Subject: [python-win32] Accessing Documentation Through Command Prompt / Help File In-Reply-To: <251460BF-2E36-4919-9450-6A537E8E9B01@hxcore.ol> References: <251460BF-2E36-4919-9450-6A537E8E9B01@hxcore.ol> Message-ID: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-keybd_event Personally, I?ve been using pyautogui a lot to do mostly mouse input (but it handles keyboard operations too)? It seems that there isn?t a lot of MSDN documentation from Microsoft on this subject though. Steven From: python-win32 On Behalf Of Tommy Weber Sent: Sunday, April 9, 2023 10:17 AM To: python-win32 at python.org Subject: [python-win32] Accessing Documentation Through Command Prompt / Help File Hello all, First off thank you to the creators of this project! It seems incredibly useful. Is there a more thorough version of the documentation than the online help version and if so how can I access it? I tried looking for a help file in the ?.venv\Lib? path where it is installed but had no luck. I found plenty of Demo files though. The online documentation seems very helpful although it is lacking in details. For instance, in the link below it specifies the dwFlags but then does not mention the flag options. Is there another place I could find this information? https://mhammond.github.io/pywin32/win32api__keybd_event_meth.html dwFlags=0 : DWORD Flags specifying various function options Please note my Python is rusty. I am used to PowerShell. Feedback would be greatly appreciated! Kind regards, Tom -------------- next part -------------- An HTML attachment was scrubbed... URL: From web4zn at hotmail.com Fri Apr 14 05:03:21 2023 From: web4zn at hotmail.com (Liu Gin) Date: Fri, 14 Apr 2023 09:03:21 +0000 Subject: [python-win32] win32api.pyd will be block by smart app control in win11 Message-ID: I pack my python code into exe, and run in win11 with Smart App Control on. is there anyone meet this problem? how can I fix or pass it? Best Regards Leen -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot 2023-04-14 012420.png Type: image/png Size: 42575 bytes Desc: Screenshot 2023-04-14 012420.png URL: From antoine.ferron at bitlogik.fr Fri Apr 14 09:10:45 2023 From: antoine.ferron at bitlogik.fr (Antoine FERRON) Date: Fri, 14 Apr 2023 15:10:45 +0200 Subject: [python-win32] win32api.pyd will be block by smart app control in win11 In-Reply-To: References: Message-ID: <8B443ACA-9118-4F63-9CBE-031D93CC2DA8@getmailspring.com> Probably you can code sign the pyd with your certificate (valid from Microsoft chain). This looks like the cause is the pyd has no signature, once signed (as a DLL) it should work. That's the same way you sign the exe (if you do so, and I'm advise to do so). _____________________________________ Antoine FERRON Pr?sident ? BitLogiK bitlogik.fr (https://bitlogik.fr) ? PGP Key ID#22F95B31 (https://keys.openpgp.org/search?q=antoine.ferron%40bitlogik.fr) On Apr 14 2023, at 11:03 am, Liu Gin wrote: > > I pack my python code into exe, and run in win11 with Smart App Control on. > is there anyone meet this problem? > how can I fix or pass it? > > Best Regards > Leen > _______________________________________________ > python-win32 mailing list > python-win32 at python.org > https://mail.python.org/mailman/listinfo/python-win32 -------------- next part -------------- An HTML attachment was scrubbed... URL: From oudouxin at gmail.com Sat Apr 15 17:27:47 2023 From: oudouxin at gmail.com (Wuping Xin) Date: Sat, 15 Apr 2023 21:27:47 +0000 Subject: [python-win32] in-process COM DLL in Python In-Reply-To: References: Message-ID: I'd like to return another Python object, using a method of a COM object defined using Python, something like below - is that doable? For in process COM object defined through Python, is there any limitation about the types that can be returned from COM method? class Person: _public_methods_ = ["Name"] def __init__(self, name, age): self.name = name self.age = age def Name(self, age = None): return self.name # Define a Python class that will be registered as a COM object class MyCOMObject: _public_methods_ = ["GetPerson"] def GetPerson(self, name, age): p = Person(name, age) my_variant = pywintypes.VARIANT(p, VARIANT.VT_DISPATCH) return my_variant # Register the class as a COM object win32com.server.register.UseCommandLine(MyCOMObject) -------------- next part -------------- An HTML attachment was scrubbed... URL: From skippy.hammond at gmail.com Sat Apr 15 22:00:02 2023 From: skippy.hammond at gmail.com (Mark Hammond) Date: Sun, 16 Apr 2023 12:00:02 +1000 Subject: [python-win32] in-process COM DLL in Python In-Reply-To: References: Message-ID: <74c5b430-5165-9129-65ef-6bfbd32f9847@gmail.com> You should be able to wrap a Person object - something like ob = win32com.server.util.wrap(Person(...)) - and just return that. You probably don't need the VARIANT dance, it should just work based on the type returned being a Dispatch wrapper. HTH, Mark On 16/4/2023 7:27 am, Wuping Xin wrote: > I'd like to return another Python object,? using a method of a COM > object defined using Python, something like below - is that doable? > For in process COM object defined through Python,? is there any > limitation about the types that can be returned from COM method? > > class?Person: > ? ? _public_methods_?=?["Name"] > > ? ? def?__init__(self,?name,?age): > ? ? ? ? self.name?=?name > ? ? ? ? self.age?=?age > > ? ? def?Name(self,?age?=?None): > ? ? ? ? return?self.name > > > #?Define?a?Python?class?that?will?be?registered?as?a?COM?object > class?MyCOMObject: > ? ? _public_methods_?=?["GetPerson"] > > *def?GetPerson(self,?name,?age):* > ? ? ? ? p?=?Person(name,?age) > my_variant?=?pywintypes.VARIANT(p,?VARIANT.VT_DISPATCH) > ? ? ? ? return?my_variant > > #?Register?the?class?as?a?COM?object > > win32com.server.register.UseCommandLine(MyCOMObject) > > _______________________________________________ > python-win32 mailing list > python-win32 at python.org > https://mail.python.org/mailman/listinfo/python-win32 -------------- next part -------------- An HTML attachment was scrubbed... URL: From oudouxin at gmail.com Sat Apr 15 21:50:31 2023 From: oudouxin at gmail.com (Wuping Xin) Date: Sun, 16 Apr 2023 01:50:31 +0000 Subject: [python-win32] in-process COM DLL in Python In-Reply-To: References: Message-ID: Forget it. I figured it our by looking into Chapter 12 of the Book - Python Programming On Win32. What a Bible it is. Cheers. ------ Original Message ------ >From "Wuping Xin" To python-win32 at python.org Date 4/15/2023 5:27:47 PM Subject in-process COM DLL in Python >I'd like to return another Python object, using a method of a COM >object defined using Python, something like below - is that doable? >For in process COM object defined through Python, is there any >limitation about the types that can be returned from COM method? > >class Person: > _public_methods_ = ["Name"] > > def __init__(self, name, age): > self.name = name > self.age = age > > def Name(self, age = None): > return self.name > > ># Define a Python class that will be registered as a COM object >class MyCOMObject: > _public_methods_ = ["GetPerson"] > > def GetPerson(self, name, age): > p = Person(name, age) > my_variant = pywintypes.VARIANT(p, VARIANT.VT_DISPATCH) > return my_variant > ># Register the class as a COM object > >win32com.server.register.UseCommandLine(MyCOMObject) -------------- next part -------------- An HTML attachment was scrubbed... URL: From wuping at caliper.com Sun Apr 16 09:28:48 2023 From: wuping at caliper.com (Wuping Xin) Date: Sun, 16 Apr 2023 13:28:48 +0000 Subject: [python-win32] win32com, server/policy.py bug? policy.py Line 639 In-Reply-To: <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> References: <1528ce55-1bd4-7966-d46f-3c3ffc3db47a@skippinet.com.au> <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> Message-ID: For the following code, the method "GetPerson" has no explicit argument (except self). class MyCOMObject: _public_methods_ = ["GetPerson"] #_reg_clsid_ = '{44ee76c7-1290-4ea6-8189-00d5d7cd712a}' #_reg_desc_ = "My COM server" #_reg_progid_ = "MyCOMObject" def get_person(self): person = Person("haha", 45) wrapped = win32com.server.util.wrap(person, useDispatcher = my_dispatcher) return wrapped When calling from VBA, like below , it works fine. Set o = CreateObject("MyCOMObject") Set p = o.get_person() However, when calling from C++, or Delphi, the following error will be thrown: "TypeError: MyCOMObject.get_person() takes 1 positional argument but 2 were given" Delphi code: procedure TForm1.Button1Click(Sender: TObject); var o: OleVariant; p: OleVariant; begin o := CreateOleObject('MyCOMObject'); p := o.get_person(); // error will be thrown s := p.name; age := p.age; ShowMessage(s); end; The fix is to change Line 639 of policy.py to the following: if len(args) == 1 and (args[0] == -2147352572 or args[0] == None): return func() else: return func(*args) -------------- next part -------------- An HTML attachment was scrubbed... URL: From wuping at caliper.com Sun Apr 16 09:48:08 2023 From: wuping at caliper.com (Wuping Xin) Date: Sun, 16 Apr 2023 13:48:08 +0000 Subject: [python-win32] win32com, server/policy.py bug? policy.py Line 639 In-Reply-To: References: <1528ce55-1bd4-7966-d46f-3c3ffc3db47a@skippinet.com.au> <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> Message-ID: A better fix is to change Line 639 of win32com/server/policy.py to the following: import inspect if len(inspect.getfullargspec(func).args) == 1: return func() else: return func(*args) Then we can make VBA, Delphi, C++ .... all clients happy. Agree? Should I submit a pull request? Wuping ------ Original Message ------ From "Wuping Xin" > To "Mark Hammond" > Cc "Python-win32 at python.org" > Date 4/16/2023 9:28:48 AM Subject win32com, server/policy.py bug? policy.py Line 639 For the following code, the method "GetPerson" has no explicit argument (except self). class MyCOMObject: _public_methods_ = ["GetPerson"] #_reg_clsid_ = '{44ee76c7-1290-4ea6-8189-00d5d7cd712a}' #_reg_desc_ = "My COM server" #_reg_progid_ = "MyCOMObject" def get_person(self): person = Person("haha", 45) wrapped = win32com.server.util.wrap(person, useDispatcher = my_dispatcher) return wrapped When calling from VBA, like below , it works fine. Set o = CreateObject("MyCOMObject") Set p = o.get_person() However, when calling from C++, or Delphi, the following error will be thrown: "TypeError: MyCOMObject.get_person() takes 1 positional argument but 2 were given" Delphi code: procedure TForm1.Button1Click(Sender: TObject); var o: OleVariant; p: OleVariant; begin o := CreateOleObject('MyCOMObject'); p := o.get_person(); // error will be thrown s := p.name; age := p.age; ShowMessage(s); end; The fix is to change Line 639 of policy.py to the following: if len(args) == 1 and (args[0] == -2147352572 or args[0] == None): return func() else: return func(*args) -------------- next part -------------- An HTML attachment was scrubbed... URL: From mhammond at skippinet.com.au Mon Apr 17 08:14:31 2023 From: mhammond at skippinet.com.au (Mark Hammond) Date: Mon, 17 Apr 2023 22:14:31 +1000 Subject: [python-win32] win32com, server/policy.py bug? policy.py Line 639 In-Reply-To: References: <1528ce55-1bd4-7966-d46f-3c3ffc3db47a@skippinet.com.au> <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> Message-ID: <4287db71-984c-60e7-c533-0f6b1101daca@skippinet.com.au> On 16/4/2023 11:48 pm, Wuping Xin wrote: > A better fix is to change Line 639 of win32com/server/policy.py to the > following: > > ????????????????????import?inspect > ????????????????????if?len(inspect.getfullargspec(func).args)?==?1: > ????????????????????????return?func() > ????????????????????else: > ????????????????????????return?func(*args) > > Then we can make VBA, Delphi, C++ .... all clients happy. > > Agree? Should I submit a pull request? I'm not sure ATM - I'd be quite surprised if there was a bug in COM functions with no args, so it may be more subtle than that. But you should certainly get either a PR or issue on github for this, ideally with a complete repro. It might be quite some time (ie, many weeks) before I can look at this in more detail. Thanks, Mark > > Wuping > > ------ Original Message ------ > From "Wuping Xin" > To "Mark Hammond" > Cc "Python-win32 at python.org" > Date 4/16/2023 9:28:48 AM > Subject win32com, server/policy.py bug? policy.py Line 639 > >> For the following code, the method "GetPerson" has no explicit >> argument (except self). >> classMyCOMObject: >> _public_methods_=["GetPerson"] >> #_reg_clsid_?=?'{44ee76c7-1290-4ea6-8189-00d5d7cd712a}' >> #_reg_desc_?=?"My?COM?server" >> #_reg_progid_?=?"MyCOMObject" >> defget_person(self): >> person=Person("haha",45) >> wrapped=win32com.server.util.wrap(person,useDispatcher=my_dispatcher) >> returnwrapped >> When calling from VBA, like below , it works fine. >> ? ? Set o = CreateObject("MyCOMObject") >> ? ? Set p = o.get_person() >> However, when calling from C++, or Delphi, the following error will >> be thrown: >> /"TypeError: MyCOMObject.get_person() takes 1 positional argument but >> 2 were given"/ >> // >> Delphi code: >> /procedure TForm1.Button1Click(Sender: TObject); / >> /var / >> /? o: OleVariant; / >> /? p: OleVariant; / >> /begin / >> /? o := CreateOleObject('MyCOMObject'); / >> /*p := o.get_person()*; // error will be thrown / >> /? s := p.name; / >> /? age := p.age; / >> /? ShowMessage(s); / >> /end;/ >> // >> The fix is to change Line 639 of policy.py to the following: >> iflen(args)==1and(args[0]==-2147352572orargs[0]==None): >> returnfunc() >> else: >> returnfunc(*args) -------------- next part -------------- An HTML attachment was scrubbed... URL: From wuping at caliper.com Mon Apr 17 08:42:14 2023 From: wuping at caliper.com (Wuping Xin) Date: Mon, 17 Apr 2023 12:42:14 +0000 Subject: [python-win32] win32com, server/policy.py bug? policy.py Line 639 In-Reply-To: <4287db71-984c-60e7-c533-0f6b1101daca@skippinet.com.au> References: <1528ce55-1bd4-7966-d46f-3c3ffc3db47a@skippinet.com.au> <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> <4287db71-984c-60e7-c533-0f6b1101daca@skippinet.com.au> Message-ID: Thanks. I'll submit a PR. When calling from a Delphi COM client (using OleVariant ), arg[0] will be set by Delphi a value of 0x8002000C, when the target Python method has NO argument (i.e., taking only "self"). This makes args non-empty. When calling from a C++ MFC/COM client, arg[0] will be set a value of "None", when the target Python method has NO argument (i.e., talking only "self"). This makes args non-empty. The following code would be a "protection" for parameterless Python method. import inspect if len(inspect.getfullargspec(func).args) == 1: return func() else: return func(*args) Wuping ------ Original Message ------ From "Mark Hammond" > To "Wuping Xin" > Cc "Python-win32 at python.org" > Date 4/17/2023 8:14:31 AM Subject Re: win32com, server/policy.py bug? policy.py Line 639 WARNING EXTERNAL EMAIL On 16/4/2023 11:48 pm, Wuping Xin wrote: A better fix is to change Line 639 of win32com/server/policy.py to the following: import inspect if len(inspect.getfullargspec(func).args) == 1: return func() else: return func(*args) Then we can make VBA, Delphi, C++ .... all clients happy. Agree? Should I submit a pull request? I'm not sure ATM - I'd be quite surprised if there was a bug in COM functions with no args, so it may be more subtle than that. But you should certainly get either a PR or issue on github for this, ideally with a complete repro. It might be quite some time (ie, many weeks) before I can look at this in more detail. Thanks, Mark Wuping ------ Original Message ------ From "Wuping Xin" > To "Mark Hammond" > Cc "Python-win32 at python.org" > Date 4/16/2023 9:28:48 AM Subject win32com, server/policy.py bug? policy.py Line 639 For the following code, the method "GetPerson" has no explicit argument (except self). class MyCOMObject: _public_methods_ = ["GetPerson"] #_reg_clsid_ = '{44ee76c7-1290-4ea6-8189-00d5d7cd712a}' #_reg_desc_ = "My COM server" #_reg_progid_ = "MyCOMObject" def get_person(self): person = Person("haha", 45) wrapped = win32com.server.util.wrap(person, useDispatcher = my_dispatcher) return wrapped When calling from VBA, like below , it works fine. Set o = CreateObject("MyCOMObject") Set p = o.get_person() However, when calling from C++, or Delphi, the following error will be thrown: "TypeError: MyCOMObject.get_person() takes 1 positional argument but 2 were given" Delphi code: procedure TForm1.Button1Click(Sender: TObject); var o: OleVariant; p: OleVariant; begin o := CreateOleObject('MyCOMObject'); p := o.get_person(); // error will be thrown s := p.name; age := p.age; ShowMessage(s); end; The fix is to change Line 639 of policy.py to the following: if len(args) == 1 and (args[0] == -2147352572 or args[0] == None): return func() else: return func(*args) -------------- next part -------------- An HTML attachment was scrubbed... URL: From wuping at caliper.com Mon Apr 17 09:48:33 2023 From: wuping at caliper.com (Wuping Xin) Date: Mon, 17 Apr 2023 13:48:33 +0000 Subject: [python-win32] win32com, server/policy.py bug? policy.py Line 639 In-Reply-To: References: <1528ce55-1bd4-7966-d46f-3c3ffc3db47a@skippinet.com.au> <7cc2794e-1834-ee05-593c-9b1d54b1eb5b@skippinet.com.au> <4287db71-984c-60e7-c533-0f6b1101daca@skippinet.com.au> Message-ID: I created a new issue (with sample Delphi project to replicate the issue, including the Python source file where the COM server is defined): https://github.com/mhammond/pywin32/issues/2043 And I submit a PR: https://github.com/mhammond/pywin32/pull/2044 Thank you. Wuping ------ Original Message ------ From "Wuping Xin" > To "Mark Hammond" > Cc "Python-win32 at python.org" > Date 4/17/2023 8:42:14 AM Subject Re[2]: win32com, server/policy.py bug? policy.py Line 639 Thanks. I'll submit a PR. When calling from a Delphi COM client (using OleVariant ), arg[0] will be set by Delphi a value of 0x8002000C, when the target Python method has NO argument (i.e., taking only "self"). This makes args non-empty. When calling from a C++ MFC/COM client, arg[0] will be set a value of "None", when the target Python method has NO argument (i.e., talking only "self"). This makes args non-empty. The following code would be a "protection" for parameterless Python method. import inspect if len(inspect.getfullargspec(func).args) == 1: return func() else: return func(*args) Wuping ------ Original Message ------ From "Mark Hammond" > To "Wuping Xin" > Cc "Python-win32 at python.org" > Date 4/17/2023 8:14:31 AM Subject Re: win32com, server/policy.py bug? policy.py Line 639 WARNING EXTERNAL EMAIL On 16/4/2023 11:48 pm, Wuping Xin wrote: A better fix is to change Line 639 of win32com/server/policy.py to the following: import inspect if len(inspect.getfullargspec(func).args) == 1: return func() else: return func(*args) Then we can make VBA, Delphi, C++ .... all clients happy. Agree? Should I submit a pull request? I'm not sure ATM - I'd be quite surprised if there was a bug in COM functions with no args, so it may be more subtle than that. But you should certainly get either a PR or issue on github for this, ideally with a complete repro. It might be quite some time (ie, many weeks) before I can look at this in more detail. Thanks, Mark Wuping ------ Original Message ------ From "Wuping Xin" > To "Mark Hammond" > Cc "Python-win32 at python.org" > Date 4/16/2023 9:28:48 AM Subject win32com, server/policy.py bug? policy.py Line 639 For the following code, the method "GetPerson" has no explicit argument (except self). class MyCOMObject: _public_methods_ = ["GetPerson"] #_reg_clsid_ = '{44ee76c7-1290-4ea6-8189-00d5d7cd712a}' #_reg_desc_ = "My COM server" #_reg_progid_ = "MyCOMObject" def get_person(self): person = Person("haha", 45) wrapped = win32com.server.util.wrap(person, useDispatcher = my_dispatcher) return wrapped When calling from VBA, like below , it works fine. Set o = CreateObject("MyCOMObject") Set p = o.get_person() However, when calling from C++, or Delphi, the following error will be thrown: "TypeError: MyCOMObject.get_person() takes 1 positional argument but 2 were given" Delphi code: procedure TForm1.Button1Click(Sender: TObject); var o: OleVariant; p: OleVariant; begin o := CreateOleObject('MyCOMObject'); p := o.get_person(); // error will be thrown s := p.name; age := p.age; ShowMessage(s); end; The fix is to change Line 639 of policy.py to the following: if len(args) == 1 and (args[0] == -2147352572 or args[0] == None): return func() else: return func(*args) -------------- next part -------------- An HTML attachment was scrubbed... URL: From moi15moismokerlolilol at gmail.com Sun Apr 23 10:01:15 2023 From: moi15moismokerlolilol at gmail.com (Moi15 Moi) Date: Sun, 23 Apr 2023 10:01:15 -0400 Subject: [python-win32] [DirectWrite] How to obtain fonts path via pywin32? Message-ID: Hi Is there a way to obtain the font path via pywin32? I need to communicate with DirectWrite. Here is the algorithm I would need to be able to get the fonts path based on the microsoft documentation: # DWriteCreateFactory - https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-dwritecreatefactory # IDWriteFactory3 - https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nn-dwrite_3-idwritefactory3 write_factory = DWriteCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory3), False) # GetSystemFontSet - https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nf-dwrite_3-idwritefactory3-getsystemfontset font_set = write_factory.GetSystemFontSet() # GetFontCount - https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nf-dwrite_3-idwritefontset-getfontcount for i in range(font_set.GetFontCount()): # GetFontFaceReference - https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nf-dwrite_3-idwritefontset-getfontfacereference font_face_reference = font_set.GetFontFaceReference(i) # GetFontFile - https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nf-dwrite_3-idwritefontfacereference-getfontfile font_file = font_face_reference.GetFontFile() # GetReferenceKey - https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritefontfile-getreferencekey reference_key, reference_key_size = font_file.GetReferenceKey() # GetFilePathFromKey - https://learn.microsoft.com/en-us/windows/win32/directwrite/idwritelocalfontfileloader-getfilepathfromkey path = GetFilePathFromKey(reference_key, reference_key_size) Have a nice day -------------- next part -------------- An HTML attachment was scrubbed... URL: From boskovicstefan95 at gmail.com Thu Apr 27 04:04:01 2023 From: boskovicstefan95 at gmail.com (Stefan Boskovic) Date: Thu, 27 Apr 2023 10:04:01 +0200 Subject: [python-win32] Reading IMMDevice friendly name using property store Message-ID: Hi, I'm trying to enumerate audio devices and access their friendly names with python like in this example . I've expanded on volume control example from the mail archive by Tim Roberts, I've added necessary methods to IMMDeviceEnumerator, redefined OpenPropertyStore() method in IMMDevice interface. Problem seems to be in IPropertyStore interface when defining its methods, specifically the GetValue method. I cannot find PropertyKey structure like PROPERTYKEY structure from windows SDK (propsys.h), so I tried defining my own, and I hope I'm using the correct type for PROPVARIANT argument. Also, I'm not sure where are constants like PKEY_Device_FriendlyName defined? ``` from comtypes import GUID, Structure, HRESULT, COMMETHOD, STDMETHOD, IUnknown, c_float, CoCreateInstance, CLSCTX_ALL from ctypes import POINTER from ctypes.wintypes import DWORD, BOOL, UINT, LPWSTR from win32comext.propsys import propsys # from: C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\functiondiscoverykeys_devpkey.h PKEY_Device_FriendlyName = 0xa45c254e CLSID_MMDeviceEnumerator = \ GUID('{BCDE0395-E52F-467C-8E3D-C4579291692E}') class PropertyKey(Structure): _fields_ = [("fmtid", GUID), ("pid", DWORD)] REFPROPERTYKEY = PropertyKey PROPVARIANT = propsys.PROPVARIANTType class IAudioEndpointVolume(IUnknown): _iid_ = GUID('{5CDF2C82-841E-4546-9722-0CF74078229A}') _methods_ = [ STDMETHOD(HRESULT, 'RegisterControlChangeNotify', []), STDMETHOD(HRESULT, 'UnregisterControlChangeNotify', []), STDMETHOD(HRESULT, 'GetChannelCount', []), COMMETHOD([], HRESULT, 'SetMasterVolumeLevel', (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'SetMasterVolumeLevelScalar', (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetMasterVolumeLevel', (['out', 'retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'GetMasterVolumeLevelScalar', (['out', 'retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'SetChannelVolumeLevel', (['in'], DWORD, 'nChannel'), (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'SetChannelVolumeLevelScalar', (['in'], DWORD, 'nChannel'), (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetChannelVolumeLevel', (['in'], DWORD, 'nChannel'), (['out', 'retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'GetChannelVolumeLevelScalar', (['in'], DWORD, 'nChannel'), (['out', 'retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'SetMute', (['in'], BOOL, 'bMute'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetMute', (['out', 'retval'], POINTER(BOOL), 'pbMute') ), COMMETHOD([], HRESULT, 'GetVolumeStepInfo', (['out', 'retval'], POINTER(c_float), 'pnStep'), (['out', 'retval'], POINTER(c_float), 'pnStepCount'), ), COMMETHOD([], HRESULT, 'VolumeStepUp', (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'VolumeStepDown', (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'QueryHardwareSupport', (['out', 'retval'], POINTER(DWORD), 'pdwHardwareSupportMask') ), COMMETHOD([], HRESULT, 'GetVolumeRange', (['out', 'retval'], POINTER(c_float), 'pfMin'), (['out', 'retval'], POINTER(c_float), 'pfMax'), (['out', 'retval'], POINTER(c_float), 'pfIncr') ), ] class IPropertyStore(IUnknown): _iid_ = GUID('{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}') _methods_ = [ COMMETHOD([], HRESULT, 'GetCount', (['out'], POINTER(DWORD), 'cProps') ), COMMETHOD([], HRESULT, 'GetAt', (['in'], DWORD, 'iProp'), (['out'], POINTER(PropertyKey), 'pkey') ), COMMETHOD([], HRESULT, 'GetValue', (['in'], REFPROPERTYKEY, 'key'), (['out', 'retval'], PROPVARIANT, 'pv') ), STDMETHOD('SetValue', HRESULT, []) ] pass class IMMDevice(IUnknown): _iid_ = GUID('{D666063F-1587-4E43-81F1-B948E807363F}') _methods_ = [ COMMETHOD([], HRESULT, 'Activate', (['in'], POINTER(GUID), 'iid'), (['in'], DWORD, 'dwClsCtx'), (['in'], POINTER(DWORD), 'pActivationParams'), (['out', 'retval'], POINTER(POINTER(IAudioEndpointVolume)), 'ppInterface') ), COMMETHOD([], HRESULT, 'OpenPropertyStore', (['in'], DWORD, 'stgmAccess'), (['out', 'retval'], POINTER(POINTER(IPropertyStore)), 'ppProperties') ), COMMETHOD([], HRESULT, 'GetId', (['out', 'retval'], POINTER(LPWSTR), 'ppstrId') ), STDMETHOD(HRESULT, 'GetState', []) ] pass class IMMDeviceCollection(IUnknown): _iid_ = GUID('{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}') _methods_ = [ COMMETHOD([], HRESULT, 'GetCount', (['out', 'retval'], POINTER(UINT), 'pcDevices') ), COMMETHOD([], HRESULT, 'Item', (['in'], UINT, 'nDevice'), (['out', 'retval'], POINTER(POINTER(IMMDevice)), 'ppDevice') ) ] pass class IMMDeviceEnumerator(IUnknown): _iid_ = GUID('{A95664D2-9614-4F35-A746-DE8DB63617E6}') _methods_ = [ COMMETHOD([], HRESULT, 'EnumAudioEndpoints', (['in'], DWORD, 'dataFlow'), (['in'], DWORD, 'dwStateMask'), (['out', 'retval'], POINTER(POINTER(IMMDeviceCollection)), 'ppDevices') ), COMMETHOD([], HRESULT, 'GetDefaultAudioEndpoint', (['in'], DWORD, 'dataFlow'), (['in'], DWORD, 'role'), (['out', 'retval'], POINTER(POINTER(IMMDevice)), 'ppDevices') ) ] enumerator = CoCreateInstance( CLSID_MMDeviceEnumerator, IMMDeviceEnumerator, CLSCTX_ALL ) def print_device_details(device): device_id = device.GetId() print(device_id) device.OpenPropertyStore(0) devices = enumerator.EnumAudioEndpoints(0, 1) device_count = devices.GetCount() print('device_count', device_count) for i in range(device_count): device = devices.Item(i) print_device_details(device) ``` Regards, Stefan Boskovic -------------- next part -------------- An HTML attachment was scrubbed... URL: