# Display all scripting code of window and template components

**URL:** <https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [October 18, 2018, 7:19pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262 "2018-10-18T19:19:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![chasondeshotel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/chasondeshotel/32/20032_2.png) [@chasondeshotel](https://forum.inductiveautomation.com/u/chasondeshotel)\
**Post date:** [October 18, 2018, 7:19pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/1 "2018-10-18T19:19:39Z")

</div>

Hello,

Is there a way to see the scripting code of all vision window components and template components? For instance, I need the value for template/button/mouse/mouseClicked/Script Editor, and so on and so forth across all components

My use case: I’m looking at changing database structure and would like to see what all components are making calls to the database so I can plan accordingly and minimize side effects

Thanks!

---

<div class="post-metadata">

**Author:** ![raymond1982](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/raymond1982/32/6490_2.png) [@raymond1982](https://forum.inductiveautomation.com/u/raymond1982)\
**Post date:** [October 18, 2018, 7:47pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/2 "2018-10-18T19:47:29Z")

</div>

Step 1: Get the context. I think this is familiar.

> [@Programatically search through templates?](http://forum.inductiveautomation.com/t/programatically-search-through-templates/19862/8):
>
> yes. This may require some explanation. Instead of using an event object i create a Jframe and grab the projects highest most frame reference and get it that way… I work in console a lot too and this helps. This is a singleton class which makes it nice. Load it at startup and dont worry about getting it again.Heavily unsupported. from system.util import CLIENT\_FLAG, DESIGNER\_FLAG from javax.swing import JFrame from java.awt.event import WindowEvent try: from com.inductiveautomation.ignition.d…

If the context cant be located in the script console you may have a flag that is odd.  
print the system.util.getSystemFlags() and add the resulting integer to [DESIGNER\_FLAG, 3] list.

```auto
current_flag = system.util.getSystemFlags()
ctx = self.resolveDesignerContext
# If False assumes the client context.
if current_flag not in [DESIGNER_FLAG, 3]:

```

After ensuring you have the context this should work. Update the path to your context and have fun with the joke.

Step 2:

```auto
from com.inductiveautomation.factorypmi.application.binding.action import ActionAdapter

class ScriptFinder:
	
	def __init__ (self, context):
		
		self.context = context
		if not hasattr(self.context, 'getProject'):
			raise Exception(self.getInvalidContextError(context))
	
	def getProjectResources(self):
		"""Return all project Resources."""
		return self.context.getProject().getResources()
		
	def getInvalidResourceTypeError(self, resource_type):
		"""Return formatted error message."""
		return 'Invalid Resource Type "%s". Options are: %s || %s.' % (
			resource_type, self.getWindowResourceType(), self.getTemplateResourceType())

	def getInvalidContextError(self, context):
		"""Return formatted error message."""
		return 'Invalid Context Reference "%s". Hint Context must support getProject method' % str(type(context))
		
	def objectSearch(self, fpmiObject, array):
		"""
		NOTES: 
		: This method takes an JComponent
		: and an array reference it will recursivley 
		: walk the component chain accumulating members until 
		: reaching the last container.
		
		Arg(s):
		: [fpmiObject] DataType: JComponent
		:	Example: Jframe, Jdialog, FMPI Root Container,
		: [array] DataType: list
		:	Example: []
		"""
		try:
			for component in fpmiObject.getComponents():
				array.append(component)
				self.objectSearch(component, array)
		except AttributeError:
			return

	def getAllComponentsForFpmiObject(self, fpmiObject):
		"""
		NOTES: 
		: Method takes a top level jcomponent and calls the
		: getComponents method. If the result is an AttributeError
		: the array is returned. If there are results both the array
		: reference and the component are passed to a recursive function
		: that will go throught the component chain.
		
		Arg(s):
		: [fpmiObject] DataType: JComponent
		: Example: Jframe, Jdialog, FMPI Root Container,
		"""
		components_array = []
		try:
			for component in fpmiObject.getComponents():
				components_array.append(component)
				self.objectSearch(component, components_array)
		except AttributeError:
			pass		
		return components_array
	
	def getProjectResourcesByType(self, resource_type):
		"""
		NOTES:
		: Filter resource array on type.
		Arg(s):
		: [resource_type] DataType: String
		:	Example: "window", "component-template"
		"""
		return [
			resource for resource in self.getProjectResources() 
			if resource.getResourceType() == resource_type
		]
		
	def getWindowResourceType(self):
		"""Returns windows resource type."""
		return 'window'
	
	def getTemplateResourceType(self):
		"""Returns template resource type."""
		return 'component-template'	
	
	
	def getSerializedReferenceFromResource(self, resource_type):
		"""
		NOTES:
		: Returns a reusable function for the deserialization of 
		: the requested types. Reduces process overhead for iterative
		: resource assessment.
		
		Arg(s):
		: [resource_type] DataType: String
		: Example: "window", "component-template"
		"""
	
		deserializer = self.context.createDeserializer()
		deserialize = deserializer.deserialize
		
		def windowInner(resource):
			"""
			NOTES:
			: Inner Function that supports deserialization of window 
			: resources. The window root objects support a different method than
			: templates for retrieving the bytesArray.
			
			Arg(s)
			: [resource] DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
			"""
			code = deserialize(resource.getData()).getRootObjects()[0].getSerializedCode()
			return deserialize(code).getRootObjects()[0]
		
		def templateInner(resource):
			"""
			NOTES:
			: Inner Function that supports deserialization of template
			: resources. The template root objects support a different method than
			: templates for retrieving the bytesArray.
			
			Arg(s)
			: [resource] DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
			:
			"""
			code = deserialize(resource.getData()).getRootObjects()[0].getSerializedBytes()
			return deserialize(code).getRootObjects()[0]
		
		if resource_type == self.getWindowResourceType():
			return windowInner
		elif resource_type == self.getTemplateResourceType():
			return templateInner
		raise Exception(self.getInvalidResourceTypeError(resource_type))
			
	
	def getDeSerializedResources(self, resource_type, resource_array):
		"""
		NOTES:
		: Return an array of deserialized project resoures.
		
		Arg(s)
		: [resource_type] DataType: String
		: Example: "window", "component-template"
		: [resource_array] DataType: list
		: Example: []
		"""
		deserializer = self.getSerializedReferenceFromResource(resource_type)
		return [deserializer(resource) for resource in resource_array]
	
	
	def getComponentAdapterGetter(self, resource):
		"""
		NOTES:
		: Returns an uncalled method for use in iteration.
		: This method gets all adapteres associated for the
		: component passed in.
		
		Arg(s)
		: [resource] DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
		:  
		"""		
		return resource.getInteractionController().getAllAdaptersForTarget
	
	
	def getValidResourceType(self):
		"""Returns array of valid resource types."""
		return [self.getWindowResourceType(), self.getTemplateResourceType()]
	
	def isResourceTypeValid(self, resource_type):
		"""Checks resource type for validity."""
		return resource_type in self.getValidResourceType()
	
	def getObjectName(self, resource):
		"""Return object name."""
		return str(resource.getTitle() if hasattr(resource, 'getTitle') else resource.getName())
		
	def getActionAdatpersforComponent(self, resource, component):
		"""Returns filtered array of Action Adapters for component."""
		adapterGetter = self.getComponentAdapterGetter(resource)
		return [adapter for adapter in adapterGetter(component) if isinstance(adapter, ActionAdapter)]
	
	
	def getJythonCodeForResourceComponents(self, resource_type):
		"""
		NOTES:
		: Returns a dictionary of resource: {components: {code: ''}}.
		: Process acquires resources of specified type and iterates
		: over all components action adapters.
		
		Arg(s)
		: [resource_type] DataType: String
		: Example: "window", "component-template"
		"""	
		# Test validity of type.
		if self.isResourceTypeValid(resource_type):
			resource_component_code_map = {}
			#Acquire resource data for type.
			resources = self.getProjectResourcesByType(resource_type)
			# Iterate through deserialized resources.
			for resource in self.getDeSerializedResources(resource_type, resources):
				resource_name = self.getObjectName(resource)
				# Get all components.
				components = self.getAllComponentsForFpmiObject(resource)
				if components:
					resource_component_code_map[resource_name] = {}
					#Iterate over component.
					for component in components:
						component_name = self.getObjectName(component)
						# Get adapters for component and iterate filtering on action adapters.
						for adapter in self.getActionAdatpersforComponent(resource, component):
							# Create entry in dictionary if not present.
							if component_name not in resource_component_code_map[resource_name]:
								resource_component_code_map[resource_name][component_name] = {}
							# Get code from action adapter.
							code = adapter.getJythonCode()
							# Get component method associated with the code.
							method_name = adapter.getMethodDescriptor().getName()
							# Update resource map.
							resource_component_code_map[resource_name][component_name][method_name] = code
							
			return resource_component_code_map
		
		raise Exception(self.getInvalidResourceTypeError(resource_type))
		return {}

	def getAllWindowsAllComponentsJythonCode(self):
		""" Returns dictionary of window resource: {components: {code: ''}}."""
		return self.getJythonCodeForResourceComponents(self.getWindowResourceType())

	def getAllTemplatesAllComponentsJythonCode(self):
		""" Returns dictionary of template resource: {components: {code: ''}}."""
		return self.getJythonCodeForResourceComponents(self.getTemplateResourceType())

	def prettyPrint(self, output):
		print system.util.jsonEncode(output, 4)

context = project.Resources.Context.getContext() # <- this must be correct
sf = ScriptFinder(context)

sf.prettyPrint(sf.getAllWindowsAllComponentsJythonCode())

sf.prettyPrint(sf.getAllTemplatesAllComponentsJythonCode())

```

---

<div class="post-metadata">

**Author:** ![lstanczyk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lstanczyk/32/24686_2.png) [@lstanczyk](https://forum.inductiveautomation.com/u/lstanczyk)\
**Post date:** [July 13, 2023, 4:54pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/3 "2023-07-13T16:54:57Z")

</div>

This does not seem to work with 8.1. Has anybody converted it to 8.1 compatible version?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [July 13, 2023, 5:29pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/4 "2023-07-13T17:29:10Z")

</div>

Most of the code should still be valid, you'll just have to extract the resources from the project differently. Some reference points to start from:

> [@Viewing more recently modified resources: possible?](https://forum.inductiveautomation.com/t/viewing-more-recently-modified-resources-possible/70585/2):
>
> If you're using my [Ignition Extensions](https://forum.inductiveautomation.com/t/ignition-extensions-convenience-utilities-for-advanced-users/64615) module, this is pretty trivial to do with the system.project.getProject() method: from com.inductiveautomation.ignition.common.project.resource import ResourceType from com.inductiveautomation.ignition.common.util import ResourceUtil def getMostRecent(moduleId, typeId): project = system.project.getProject() allResources = [ resource for resource in project.getResourcesOfType(ResourceType(moduleId, typeId)) if project.isLocal(resource.resourcePa…

> [@Auto-Export all Vision window Documentation](https://forum.inductiveautomation.com/t/auto-export-all-vision-window-documentation/72643/2):
>
> With [Ignition Extensions](https://forum.inductiveautomation.com/t/ignition-extensions-convenience-utilities-for-advanced-users/64615) installed, you could call system.project.getProject() to get an instance of the [Project](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.26/com/inductiveautomation/ignition/common/project/Project.html) Java class. From there, call getResourcesOfType with a resource type of com.inductiveautomation.factorypmi.common.VisionModule.WINDOW\_RESOURCE (this'll only work directly in the designer; doing it from the gateway scope will be a bit trickier). That will give you a list of ProjectResources, which have a [getDocumentation](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.26/com/inductiveautomation/ignition/common/project/resource/ProjectResource.html#getDocumentation()) method. Technically, Ignition Extensions is not required (you c…

> [@Autogenerate Views inside the Perspective View Folder Structure (Self Aware SCADA)](https://forum.inductiveautomation.com/t/autogenerate-views-inside-the-perspective-view-folder-structure-self-aware-scada/63204/2):
>
> I can offer some tips, but be aware that everything you do here is outside the realm of supported territory, so you will have to do a lot of the legwork yourself. To start, you’ll need to get to the project. from com.inductiveautomation.ignition.designer import IgnitionDesigner context = IgnitionDesigner.getFrame().context Will get you a [DesignerContext](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.19/com/inductiveautomation/ignition/designer/model/DesignerContext.html). DesignerContext has a method getProject(), which gives you a [DesignableProject](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.19/com/inductiveautomation/ignition/designer/project/DesignableProject.html). DesignableProject has a ton of utility methods. You will …

---

<div class="post-metadata">

**Author:** ![lstanczyk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lstanczyk/32/24686_2.png) [@lstanczyk](https://forum.inductiveautomation.com/u/lstanczyk)\
**Post date:** [July 13, 2023, 6:12pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/5 "2023-07-13T18:12:19Z")

</div>

I am trying to do this by not installing additional modules (security concerns that our admins have).  
I want to contain all functionality in the global project's script library so that I can just call it from the scripting console.  
so far i am able to get the resources like so:

```auto
from com.inductiveautomation.ignition.designer import IgnitionDesigner  
from com.inductiveautomation.ignition.common.project import *  
context = IgnitionDesigner.getFrame().getContext()  
resources = context.getProject().getResources()

for r in resources:   
    r.getData()

```

the thing is that I get a byte array's that I am not sure how to convert to some usable format.

```auto
array('b', [31, -117, 8, 0, 0, 0, 0, 0, 0, 0, -51, 84, 93, 111, -37, 32, 20, 125, 110, 

```

PS. My ultimate goal is to create a script that will iterate over all scripting resources and write them into the fileststem, then show a popup input prompt for a commit message and from there call git to check everything in to the repository so we can version control. Like I said I am limited to scripts as we do not want to install any modules.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [July 13, 2023, 6:19pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/6 "2023-07-13T18:19:07Z")

</div>

The code to deserialize a byte array into a Vision window is in the script posted above; it's unchanged from whatever version that was written in.

You're going to be swimming upstream the entire time you're doing this, and subject to breaking changes every time you update Ignition. I'd really recommend against it.

As of 8.1.25 you can set the project to store Vision windows in human-readable XML. It's not particular friendly to diff, but avoids all of this hacking about with the resource internals.

---

<div class="post-metadata">

**Author:** ![lstanczyk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lstanczyk/32/24686_2.png) [@lstanczyk](https://forum.inductiveautomation.com/u/lstanczyk)\
**Post date:** [July 13, 2023, 6:30pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/7 "2023-07-13T18:30:49Z")

</div>

Do you have a good method on how to manage code with version control?  
I am also looking into the project export - all script library files are there in plain text, so that would work potentially, but windows' scripts are contained in the binary file.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [July 13, 2023, 6:45pm UTC](https://forum.inductiveautomation.com/t/display-all-scripting-code-of-window-and-template-components/20262/8 "2023-07-13T18:45:10Z")

</div>

> As of 8.1.25 you can set the project to store Vision windows in human-readable XML. It's not particular friendly to diff, but avoids all of this hacking about with the resource internals.
