Search code examples
ironpythoniconsironpython-studio

Accessing embedded resources in IronPython


I'm developing a Windows Forms Application in IronPython Studio. I want to choose an Icon for my project but both of these fail: 1- Form Properties window -> Icon (choose a *.ico file) a compile-time error occurs and is related to IronPython.targets file

The "IronPythonCompilerTask" task failed unexpectedly. System.ArgumentNullException: Value cannot be null.

2- I add a *.ico file to Project (Project -> Add -> Existing Item) and in its properties, change the 'Build Action' to 'Embedded Resource' now I cannot use System.Reflection.Assembly to gain access to this resource my code:

self.Icon = Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream('IronPythonWinApp.myIcon.ico'))

in runtime it throws an exception:

The invoked member is bot supported in a dynamic assembly

Does anyone know a better (best?) way to add an icon to an IronPython WinForms ?

thanks


Solution

  • IronPython is a dynamic scripting language; it is interpreted at runtime from the script files themselves, rather than being compiled into an assembly. Since there is no compiled assembly, you cannot have an embedded resource. Here are two ways of adding an icon to a form in IronPython:

    First, you could include the icon as a loose file alongside the python scripts. You can then create the icon object by passing the icon filename to the System.Drawing.Icon constructor. Here is an example of this scenario, where the main python script and the icon are deployed in the same directory. The script uses the solution found here to find the directory.

    import clr
    clr.AddReference('System.Drawing')
    clr.AddReference('System.Windows.Forms')
    
    import os
    import __main__
    from System.Drawing import Icon
    from System.Windows.Forms import Form
    
    scriptDirectory = os.path.dirname(__main__.__file__)
    iconFilename = os.path.join(scriptDirectory, 'test.ico')
    icon = Icon(iconFilename)
    
    form = Form()
    form.Icon = icon
    form.ShowDialog()
    

    Alternatively, you can load an icon that is included as an embedded resource in a .NET assembly that is written in C#, for instance.

    import clr
    clr.AddReference('System.Drawing')
    clr.AddReference('System.Windows.Forms')
    
    from System.Drawing import Icon
    from System.Reflection import Assembly
    from System.Windows.Forms import Form
    
    assembly = Assembly.LoadFile('C:\\code\\IconAssembly.dll')
    stream = assembly.GetManifestResourceStream('IconAssembly.Resources.test.ico')
    icon = Icon(stream)
    
    form = Form()
    form.Icon = icon
    form.ShowDialog()