diff --git a/LICENSE b/LICENSE index a81095b..fb1611b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,67 +1,45 @@ -Siemens Inner Source License v1.4 - -Preamble -This License serves the purpose to facilitate exchange of source code among Siemens’ AFFILIATES on an internal code sharing platform. It applies to Siemens Aktiengesellschaft and all of its AFFILIATES that either have concluded the “Agreement on the use of the Inner Source Platform in collaborative software development projects” with Siemens Aktiengesellschaft (“AGREEMENT”) or participate in the inner source code sharing by means of any other valid agreement. - -1. Definitions -Terms with capital letters are defined in Exhibit 1 to this Annex 4. - -2. Grants -To the extent and as long as it has the right to do so, the PARTICIPATING SIEMENS ENTITY, which has uploaded the SOFTWARE, as well as the Siemens Aktiengesellschaft grant all other PARTICIPATING SIEMENS ENTITIES with respect to the SOFTWARE and the associated documentation file(s) under its copyrights and intellectual property rights a non-exclusive, worldwide, and irrevocable right and license to: - i. use, have used, copy, have copied, modify, have modified the SOFTWARE, - ii. incorporate and have incorporated the SOFTWARE and/or modified versions thereof in binary form into PRODUCTS; and - iii. to market, have market, distribute, have distributed, make available, have made available (including online distribution and hosting as a service) to third parties for use in virtual and/or non-virtual environments, the SOFTWARE solely in binary form and as part of PRODUCTS. If the SOFTWARE can only be used and distributed in source code form (e.g. scripting languages), the rights granted under this section ii.-iii.) shall also apply to the source code of the SOFTWARE. - iv. deposit the source code of the SOFTWARE with third parties acting as escrow agents and grant customers of PRODUCTS, into which the SOFTWARE or modified versions thereof have been incorporated, non-exclusive rights to use and modify the SOFTWARE under the conditions specified in the escrow agreement for the purpose of manufacturing and using such PRODUCTS, which incorporate the SOFTWARE and modified versions thereof. - -If SOFTWARE is software which has been developed and/or enhanced by or for a SIEMENS GAS AND POWER OPERATING COMPANY and for which the SIEMENS GAS AND POWER OPERATING COMPANY had granted to INNER SOURCE CONTRIBUTOR corresponding sublicensing rights, the license of this Section 2 shall be limited to the SIEMENS CURRENT FIELD. - -3. Restrictions -For avoidance of doubt, a PARTICIPATING SIEMENS ENTITY shall not be entitled to grant third parties exclusive rights to the SOFTWARE and to make available to third parties its PRODUCTS containing SOFTWARE and/or modified versions thereof under license terms that violate or conflict with the terms of this license or any applicable agreement referring to this license. -Furthermore all PARTICIPATING SIEMENS ENTITIES shall - i. comply with all current restrictions, obligations and guidelines posted on or referenced by the SIEMENS CODE REPOSITORY and additional restrictions and/or obligations – if any available – in an optional file named “RESTRICTIONS.md file” associated with the respective SOFTWARE on the SIEMENS CODE REPOSITORY; and - ii. use reasonable efforts to make all enhancements and/or modifications made to the SOFTWARE available to all other PARTICIPATING SIEMENS ENTITY on the SIEMENS CODE REPOSITORY under the terms of this license, as amended from time to time. - -4. Liability -All PARTICIPATING SIEMENS ENTITIES shall be solely responsible for their use of SOFTWARE and/or modified versions thereof and shall be liable to third parties for their PRODUCTS containing SOFTWARE and/or modified versions thereof and shall not be entitled to assert warranty or compensation claims against other PARTICIPATING SIEMENS ENTITIES for defects or third party intellectual property rights infringement in the SOFTWARE, notwithstanding any contrary provisions in the Terms and Conditions for Deliveries and Services for Siemens-internal Transactions (Siemens Conditions). - -5. Newer Versions -The license administrator of this license is Siemens Aktiengesellschaft, SOP IT. This license may be changed from time to time. Any change and its effective date have to be agreed by the Divisional Support Group / Steering Committee or any successor organization thereof. No one other than the license administrator has the right to publish the changes to this license agreed by the Divisional Support Group / Steering Committee or any successor organization thereof. The released version of this license has a unique version number. The license administrator shall publish revised and/or new versions of this license at least 30 days before the change effective date. Such revised/new versions will be similar in spirit to the current version, but may differ in detail to address new problems or concerns. Revised and/or new versions of this license released on the SIEMENS CODE REPOSITORY become binding at the given change effective date. -The SIEMENS CODE REPOSITORY shall show which version of the license applies to which SOFTWARE. - -6. Termination -If the AGREEMENT or any other agreement from which PARTICIPATING SIEMENS ENTITY derives its right to participate in the inner source code sharing terminates, the former PARTICIPATING SIEMENS ENTITY retains the right to use the SOFTWARE downloaded during the term of the respective terminated agreement under the terms of this License. In contrast, the former PARTICIPATING SIEMENS ENTITY is no longer entitled to access the SIEMENS CODE REPOSITORY or use SOFTWARE made available on the SIEMENS CODE REPOSITORY after termination of the respective agreement. - -Exhibit 1 to Annex 4 -Definitions - -"AFFILIATE" shall mean a corporation or other entity directly or indirectly, owned or controlled by, or owning or controlling, or under common control with Siemens Aktiengesellschaft where “control” shall mean to have, directly or indirectly, the power to direct or cause the direction of the management and policies of a corporation or other entity. - -“BUSINESS MANDATE” shall mean BUSINESS MANDATES published in the Business Mandate Directory of Siemens on 1 October 2019, provided that, if omissions or errors that may be contained in the Business Mandate Directory on 1 October 2019 are corrected by the Parties until the Loss of Control Date in accordance with the procedure of approval and release of the BUSINESS MANDATES of Siemens, such corrected version of the Business Mandate Directory shall apply. - -“GP CURRENT FIELD” shall mean the portfolio of products and services, including legacy products and services, of the BUSINESS as conducted on PORTFOLIO REFERENCE DATE, whereas such portfolio shall consist of: - (i) products and services set out in the BUSINESS MANDATES of the SIEMENS GAS AND POWER OPERATING COMPANY, - (ii) products and services which are actually part of the portfolio of the BUSINESS on the PORTFOLIO REFERENCE DATE and are neither set out in the BUSINESS MANDATES of the SIEMENS GAS AND POWER OPERATING COMPANY nor in the BUSINESS MANDATES of SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and - (iii) products or services which are not set out in the BUSINESS MANDATES of either Party but are on the PORTFOLIO REFERENCE DATE part of the research and development conducted by, or on behalf of, the BUSINESS, provided that, such research and development (a) has been funded by the BUSINESS prior to the PORTFOLIO REFERENCE DATE and (b) is documented in a written BUSINESS or research and development plan. - -For the avoidance of doubt, -(1) in case the products and services are set out in the BUSINESS MANDATES of both SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and the BUSINESS, such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD; -(2) in case products and services are actually part of both, the portfolio of SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and of the BUSINESS, and are not set out in either of the respective BUSINESS MANDATES, such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD; and -(3) in case the products and services are part of the research and development conducted on the PORTFOLIO REFERENCE DATE by both the BUSINESS and SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, but excluding any research and development by Siemens or its AFFILIATES (excluding SIEMENS GAS AND POWER OPERATING COMPANY) for the BUSINESS based on orders placed by the BUSINESS and where such research and development is fully funded by the BUSINESS and as set out in a list agreed between Siemens Aktiengesellschaft and SIEMENS GAS AND POWER OPERATING COMPANY, then such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD. - -“LOSS OF CONTROL DATE” shall mean the date upon which SIEMENS GAS AND POWER OPERATING COMPANY ceases to be an AFFILIATE of Siemens Aktiengesellschaft. -“PARTICIPATING SIEMENS ENTITIES” shall mean Siemens Aktiengesellschaft and all AFFILIATES that i) either have concluded or will conclude the “Agreement on the use of the Inner Source Platform in collaborative software development projects” (hereinafter referred to as “AGREEMENT”) with Siemens Aktiengesellschaft, for as long as the respective entity is a party to the AGREEMENT or that ii) participate in the inner source code sharing by means of any other valid agreement. -“PORTFOLIO REFERENCE DATE” shall mean October 1, 2019. -“PRODUCTS” are products, supplies, services, projects, solutions and systems for internal use and/or for third parties. -“SIEMENS CODE REPOSITORY” shall mean the source code management platform ‘code.siemens.com’. -“SIEMENS GROUP” shall mean Siemens Aktiengesellschaft and its AFFILIATES: -“SOFTWARE” shall mean proprietary code uploaded by a PARTICIPATING SIEMENS ENTITY to the SIEMENS CODE REPOSITORY marked as “internal project” for further use by all other PARTICIPATING SIEMENS ENTITIES. -“SIEMENS CURRENT FIELD” shall mean the portfolio of products and services, including legacy products and services, of SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, as conducted on PORTFOLIO REFERENCE DATE, whereas such portfolio shall consist of: - (i) products and services set out in the BUSINESS MANDATE of the SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, - (ii) products and services which are actually part of the portfolio of the SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, on the PORTFOLIO REFERENCE DATE and are neither set out in the BUSINESS MANDATEs of the SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, nor in the BUSINESS MANDATES of the BUSINESS, and - (iii) products and services which are not set out in the BUSINESS MANDATES of either Party but are on the PORTFOLIO REFERENCE DATE part of the research and development conducted by, or on behalf of, the SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, provided that, such research and development (a) has been funded by SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and (b) is documented in a written business or research and development plan. -For the avoidance of doubt: -(1) in case the products and services are set out in the BUSINESS MANDATES of both SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and the BUSINESS, such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD; -(2) in case products and services are actually part of both, the portfolio of SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, and of the BUSINESS, and are not set out in either of the BUSINESS MANDATES, such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD; and -(3) in case the products and services are part of the research and development conducted on the PORTFOLIO REFERENCE DATE by both the BUSINESS and SIEMENS GROUP, excluding SIEMENS GAS AND POWER OPERATING COMPANY, but excluding any research and development by the BUSINESS for the Transferor or its AFFILIATES (excluding SIEMENS GAS AND POWER OPERATING COMPANY) based on orders placed by the TRANSFEROR or its AFFILIATES (excluding SIEMENS GAS AND POWER OPERATING COMPANY) and where such research and development is fully funded by the TRANSFEROR or its AFFILIATE (excluding Gas and Power Operating Company) and as set out in a list agreed between Siemens AG and SIEMENS GAS AND POWER OPERATING COMPANY, then such products and services shall be deemed to be both within SIEMENS CURRENT FIELD and GP CURRENT FIELD. - -“TRANSFEROR” shall mean Siemens Aktiengesellschaft or its AFFILIATE ((excluding SIEMENS GAS AND POWER OPERATING COMPANY). +# Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products + +# 1. General information: Software in source code and object code + +## 1.1 Use of the Software +Siemens AG and/or a subsidiary of Siemens AG (“Siemens”) provides You royalty-free container images, application examples, sample code and software development kits (“Software”) through sharing platforms (e.g. GitHub, DockerHub, NuGet, etc.). The Software shall only be used for the development and test of software which can be used with Siemens products (“intended purpose”). The Software is non-binding and makes no claim to completeness or functionality. The Software merely offers help with typical tasks and provides an environment for developing and testing applications and other software. You Yourself are responsible for the proper and safe operation of Your products in accordance with applicable regulations and must also check the function of the results of the Software and customize Your products. Siemens reserves the right to make changes to the Software at any time without notice. Software may be provided in object code and/or source code format. Unless explicitly granted in the open source license according to article 2, You shall not decompile, translate, extract, modify or distribute the Software. + +## 1.2 Security information +Siemens provides products and solutions with industrial security functions that support the secure operation of plants, systems, machines and networks. In order to protect plants, systems, machines and networks against cyber threats, it is necessary to implement – and continuously maintain – a holistic, state-of-the-art industrial security concept. Siemens’ products and solutions constitute one element of such a concept. Customers are responsible for preventing unauthorized access to their plants, systems, machines and networks. Such systems, machines and components should only be connected to an enterprise network or the internet if and to the extent such a connection is necessary and only when appropriate security measures (e.g. firewalls and/or network segmentation) are in place. For additional information on industrial security measures that may be implemented, please visit . + +## 1.3 Compliance with Export Control Regulations +You shall comply with all applicable sanctions, embargoes and (re-)export control regulations, and, in any event, with those of the European Union and the United States of America (collectively “Export Regulations”). In particular, the information, software and documentation provided by Siemens (collectively “Licensed Material”) shall not be used, accessed or transferred, unless permitted by the Export Regulations or respective governmental licenses or approvals, (i) in or to any location prohibited by or subject to comprehensive sanctions (currently Russia, Cuba, Iran, North Korea, Syria, and the Crimea region of Ukraine, Donetsk and Luhansk regions of Ukraine) or license requirements according to the Export Regulations; (ii) by or to any individual or entity designated on a sanctioned party list of the Export Regulations; (iii) for any purpose prohibited by the Export Regulations (e.g. use in connection with armaments, nuclear technology or weapons); or (iv) to upload any content unless it is noncontrolled (e .g. in the EU: AL = N; in the U.S.: ECCN = N or EAR99). If required to enable authorities or Siemens to conduct export control checks, You, upon request by Siemens, shall promptly provide Siemens with all information pertaining to You, the intended use and the location of use of the Licensed Material. Siemens shall not be obligated to fulfill this Agreement if such fulfillment is prevented by any impediments arising out of national or international foreign trade or customs requirements or any embargoes or other sanctions. + +# 2. Open Source License for Software in source code and generated source code +In case the Software contains or generates source code the following open source license shall apply for such source code: + +MIT License +Copyright 2022 Siemens AG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# 3. Software provided in object code +For all portions of the Software that are provided in object code format the following conditions shall apply (“Royalty-Free Siemens Software Conditions”): + +## 3.1 License Grant +Siemens grants You the royalty-free, non-exclusive, non-sublicensable and non-transferable right to use, have used the Software by technically trained personnel and for the intended purpose only. + +## 3.2 Included third-party software components +Insofar as Open Source Software is included in the Software, such Open Source Software is listed in the Readme_OSS file of the Software. You are entitled to use the Open Source Software in accordance with the respective applicable license conditions of the Open Source Software. These OSS license conditions are included with Software and shall prevail over these Royalty-Free Siemens Software Conditions. The Open Source Software license conditions shall have priority also in relation to the proprietary Siemens components insofar as the Open Source Software license conditions grant You certain rights of use on the basis of the connection of OSS components with proprietary Siemens components. + +Siemens shall make available to You, at Your request, the Open Source Software source code in +return for payment of a fee to compensate for expenses insofar as the license conditions of the Open Source Software require such release of the source code. + +The Software may, in addition to Open Source Software, contain other licensed software, i.e. software which was not developed by Siemens itself, but which Siemens has obtained from third parties, e.g. Microsoft Ireland Operations Ltd, under a license. If You shall receive in such case the conditions of the respective licensor of the licensed software in the Readme_OSS file, these shall apply to the liability of the licensor in relation to You. In terms of the liability of Siemens to You, these Royalty-Free Siemens Software Conditions shall apply in each case. + +## 3.3 Disclaimer of liability +Siemens shall not assume any liability, for any legal reason whatsoever, including, without limitation, liability for the usability, availability, completeness and freedom from defects of the Software as well as for the Licensed Material and any damage caused thereby. This shall not apply in cases of mandatory liability, for example product liability law or in cases of intent, gross negligence, or culpable loss of life, bodily injury or damage to health, non-compliance with a guarantee, fraudulent non-disclosure of a defect, or culpable breach of material contractual obligations. Claims for damages arising from a breach of material contractual obligations shall however be limited to the foreseeable damage typical of the type of agreement, unless liability arises from intent or gross negligence or is based on loss of life, bodily injury or damage to health. The foregoing provisions do not imply any change in the burden of proof to Your detriment. You shall indemnify Siemens against existing or future claims of third +parties in this connection except where Siemens is mandatorily liable. + +By using the Software and the Licensed Material, You acknowledge that Siemens cannot be held liable for any damage beyond the liability provisions described. diff --git a/OpennessConsoleApplication/App.config b/OpennessConsoleApplication/App.config deleted file mode 100644 index 4bfa005..0000000 --- a/OpennessConsoleApplication/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/OpennessConsoleApplication/OpennessConsoleApplication.csproj b/OpennessConsoleApplication/OpennessConsoleApplication.csproj deleted file mode 100644 index c34f416..0000000 --- a/OpennessConsoleApplication/OpennessConsoleApplication.csproj +++ /dev/null @@ -1,122 +0,0 @@ - - - - - Debug - AnyCPU - {626B1137-31F2-4782-8386-F432FF7D01EC} - Exe - Properties - ShowScripts - ShowScripts - v4.8 - 512 - true - - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - - - C:\Program Files\Siemens\Automation\Portal V19\PublicAPI\V19\Siemens.Engineering.dll - False - - - - - - - - - - - - - - - Form - - - InputForm.cs - - - - - - - - - - {0002E157-0000-0000-C000-000000000046} - 5 - 3 - 0 - primary - False - True - - - - - False - Microsoft .NET Framework 4.8 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - InputForm.cs - - - - - copy $(TargetPath) ..\..\..\ShowScripts\OpennessExe\$(TargetName).exe - - - \ No newline at end of file diff --git a/OpennessConsoleApplication/Program.cs b/OpennessConsoleApplication/Program.cs deleted file mode 100644 index b6dc84b..0000000 --- a/OpennessConsoleApplication/Program.cs +++ /dev/null @@ -1,295 +0,0 @@ -using Siemens.Engineering; -using Siemens.Engineering.HmiUnified; -using Siemens.Engineering.HmiUnified.UI.Screens; -using Siemens.Engineering.HW; -using Siemens.Engineering.HW.Features; -using System; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Siemens.Engineering.HmiUnified.UI.ScreenGroup; -using System.Reflection; -using System.Windows; - -namespace ShowScripts -{ - class Program - { - private static Dictionary cmdArgs; - private static List deviceNames = new List(); - static void Main(string[] args) - { -#if DEBUG - Debugger.Launch(); -#endif - cmdArgs = ParseArguments(args); // e.g. export -t "PC-System_1" -P "8876" -A "C:\Program Files\Siemens\Automation\Portal V19\bin\Siemens.Automation.Portal.exe" - AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver; - if (cmdArgs.ContainsKey("-t")) - { - deviceNames = cmdArgs["-t"].Split(',').ToList(); - } - else // if no device names were set, add at least one empty entry to analysze the first device - { - deviceNames.Add(""); - } - Work(cmdArgs.ContainsKey("-P") ? int.Parse(cmdArgs["-P"]) : -1, args.Length > 0 ? (args[0].ToLower() == "import") : false, args.ToList().Contains("--overwrite"), args.ToList().Contains("--silent")); - } - static void Work(int processId = -1, bool isImport = false, bool overwrite = false, bool silent = false) - { - string screenName = ".*"; - TiaPortal tiaPortal = null; - var processes = TiaPortal.GetProcesses(); - if (processes.Count > 0) - { - try - { - if (processId == -1) // just take the first opened TIA Portal, if it is not specified - { - tiaPortal = processes.First().Attach(); - } - else - { - tiaPortal = processes.First(x => x.Id == processId).Attach(); - } - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - } - else - { - Console.WriteLine("No TIA Portal found. Please open one."); - Console.WriteLine("Press any key to close..."); - Console.ReadKey(); - return; - } - - Project tiaPortalProject = tiaPortal.Projects.FirstOrDefault(); - if (tiaPortalProject == null) - { - Console.WriteLine("Cannot find any opened TIA Portal project inside TIA Portal. Please open one."); - Console.WriteLine("If there is a project open, but this error occurs, this is a known bug in TIA Portal. Workaround: Copy the HMI and connected PLC to a new created TIA Portal project and run the tool again."); - Console.WriteLine("Press any key to close..."); - Console.ReadKey(); - return; - } - foreach (var deviceName in deviceNames) - { - var screens = GetScreens(tiaPortalProject, deviceName); - if(screens == null) - { - Console.WriteLine("Cannot find any HMI with name: " + deviceName); - Console.WriteLine("If the device exists, but this error occurs, this is a known bug in TIA Portal. Workaround: Copy the HMI and connected PLC to a new created TIA Portal project and run the tool again."); - Console.WriteLine("Press any key to close..."); - Console.ReadKey(); - return; - } - - List screenDynEvenList = new List(); - string fileDirectory = tiaPortalProject.Path.DirectoryName + "\\UserFiles\\ShowScripts_" + deviceName + "\\"; - if (!Directory.Exists(fileDirectory)) - { - Directory.CreateDirectory(fileDirectory); - } - //Console.WriteLine("export path: " + fileDirectory); - - var worker = new AddScriptsToList(); - if (!isImport) - { - worker.ExportScripts(screens, fileDirectory, screenName, deviceName, overwrite, silent); - - // run command to fix scripts with eslint rules - var processStartInfo = new ProcessStartInfo(); - processStartInfo.WorkingDirectory = fileDirectory; - processStartInfo.FileName = "cmd.exe"; - processStartInfo.Arguments = "/C npm run lint"; - Process proc = Process.Start(processStartInfo); - proc.WaitForExit(); - } - else - { - // import scripts - worker.ImportScripts(screens, fileDirectory); - tiaPortalProject.Save(); - } - } - } - - private static IEnumerable GetScreens(Project tiaProject, string deviceName) - { - var screens = GetScreens(tiaProject.Devices, deviceName); - if (screens == null) { - screens = GetScreens(tiaProject.DeviceGroups, deviceName); - } - return screens; - } - private static IEnumerable GetScreens(DeviceUserGroupComposition groups, string deviceName) - { - foreach (var group in groups) - { - var screens = GetScreens(group.Devices, deviceName); - if (screens != null) - { - return screens; - } - screens = GetScreens(group.Groups, deviceName); - if (screens != null) - { - return screens; - } - } - return null; - } - - private static IEnumerable GetScreens(DeviceComposition devices, string deviceName) - { - IEnumerable screens = null; - if (string.IsNullOrEmpty(deviceName)) - { - foreach (var device in devices) - { - screens = GetScreens(device); - if (screens != null) - { - deviceName = device.Name; - return screens; - } - } - } - else - { - var device = devices.FirstOrDefault(x => x.Name == deviceName); - if (device != null) - { - return GetScreens(device); - } - } - return null; - } - - private static IEnumerable GetScreens(Device device) - { - foreach (DeviceItem deviceItem in device.DeviceItems) - { - SoftwareContainer softwareContainer = deviceItem.GetService(); - if (softwareContainer != null && softwareContainer.Software is HmiSoftware) - { - var sw = (softwareContainer.Software as HmiSoftware); - var allScreens = sw.Screens.ToList(); - allScreens.AddRange(ParseGroups(sw.ScreenGroups)); - return allScreens; - } - } - return null; - } - - private static IEnumerable ParseGroups(HmiScreenGroupComposition parentGroups) - { - foreach (var group in parentGroups) - { - foreach (var screen in group.Screens) - { - yield return screen; - } - foreach (var screen in ParseGroups(group.Groups)) - { - yield return screen; - } - } - } - - - private static Dictionary ParseArguments(string[] args) - { - Dictionary arguments = new Dictionary(); - for (int i = 0; i < args.Length; i++) - { - if (args[i].ToCharArray()[0] == '-') - { - int x = i + 1; - if (x < args.Length) - { - if (args[x].ToCharArray()[0] != '-') - { - if (arguments.ContainsKey(args[i]) == false) - { - arguments.Add(args[i], args[x]); - } - } - } - } - } - return arguments; - } - - public static Assembly AssemblyResolver(object sender, ResolveEventArgs args) - { - int index = args.Name.IndexOf(','); - string dllPathToTry = string.Empty; - string directory = string.Empty; - if (index != -1) - { - string name = args.Name.Substring(0, index); - string path = cmdArgs.ContainsKey("-A") ? cmdArgs["-A"] : "C:\\Program Files\\Siemens\\Automation\\Portal V19\\bin\\Siemens.Automation.Portal.exe"; - if (path != null & path != string.Empty) - { - if (name == "Siemens.Engineering") - { - try - { - FileInfo exeFileInfo = new FileInfo(path); - dllPathToTry = exeFileInfo.Directory + @"\..\PublicAPI\V19\Siemens.Engineering.dll"; - } - catch (System.NullReferenceException e) - { - MessageBox.Show("Data2Unified cannot start due to an inconsistent TIA installation. Please contact support.", - "Error", - MessageBoxButton.OK, - MessageBoxImage.Error); - System.Environment.Exit(1); - } - } - else if (name == "Siemens.Engineering.Hmi") - { - try - { - FileInfo exeFileInfo = new FileInfo(path); - dllPathToTry = exeFileInfo.Directory + @"\..\PublicAPI\V19\Siemens.Engineering.Hmi.dll"; - } - catch (System.NullReferenceException e) - { - MessageBox.Show("Data2Unified cannot start due to an inconsistent TIA installation. Please contact support.", - "Error", - MessageBoxButton.OK, - MessageBoxImage.Error); - System.Environment.Exit(1); - } - } - } - - - - if (dllPathToTry != string.Empty) - { - string assemblyPath = Path.GetFullPath(dllPathToTry); - - if (File.Exists(assemblyPath)) - { - return Assembly.LoadFrom(assemblyPath); - } - else - { - MessageBox.Show("Data2Unified cannot start due to an inconsistent TIA installation. Please contact support.", - "Error", - MessageBoxButton.OK, - MessageBoxImage.Error); - System.Environment.Exit(1); - } - } - } - return null; - } - } -} \ No newline at end of file diff --git a/OpennessConsoleApplication/Properties/AssemblyInfo.cs b/OpennessConsoleApplication/Properties/AssemblyInfo.cs deleted file mode 100644 index 02d2c4e..0000000 --- a/OpennessConsoleApplication/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("TestAddin")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TestAddin")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("626b1137-31f2-4782-8386-f432ff7d01ec")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ShowScripts.sln b/ShowScripts.sln index f287fc6..aacc0d4 100644 --- a/ShowScripts.sln +++ b/ShowScripts.sln @@ -1,14 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowScripts", "ShowScripts\ShowScripts.csproj", "{712792B7-1B37-4CCF-8518-0EE6BFAFAEA1}" - ProjectSection(ProjectDependencies) = postProject - {626B1137-31F2-4782-8386-F432FF7D01EC} = {626B1137-31F2-4782-8386-F432FF7D01EC} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpennessConsoleApplication", "OpennessConsoleApplication\OpennessConsoleApplication.csproj", "{626B1137-31F2-4782-8386-F432FF7D01EC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -20,12 +15,11 @@ Global {712792B7-1B37-4CCF-8518-0EE6BFAFAEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU {712792B7-1B37-4CCF-8518-0EE6BFAFAEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU {712792B7-1B37-4CCF-8518-0EE6BFAFAEA1}.Release|Any CPU.Build.0 = Release|Any CPU - {626B1137-31F2-4782-8386-F432FF7D01EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {626B1137-31F2-4782-8386-F432FF7D01EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {626B1137-31F2-4782-8386-F432FF7D01EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {626B1137-31F2-4782-8386-F432FF7D01EC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {403DE1B6-CAEC-409B-8897-22B3B471587A} + EndGlobalSection EndGlobal diff --git a/ShowScripts/AddIn.cs b/ShowScripts/AddIn.cs index 6988ba4..94b024a 100644 --- a/ShowScripts/AddIn.cs +++ b/ShowScripts/AddIn.cs @@ -9,13 +9,14 @@ using System.IO; using Siemens.Engineering.HmiUnified.UI.ScreenGroup; using System.Diagnostics; +using System; +using System.Windows.Forms; namespace ShowScripts { public class AddIn : ContextMenuAddIn //Enthält eigentliche Funktionalität des AddIns { private readonly TiaPortal _tiaPortal; - private readonly string exeName = "ShowScripts.OpennessExe.ShowScripts.exe"; public AddIn(TiaPortal tiaPortal) : base("ShowScriptCode") //Definiert den AddIn-Namen { @@ -36,32 +37,28 @@ private void OnClickExportSilent(MenuSelectionProvider menuS #if DEBUG Debugger.Launch(); #endif - string args = "export --silent"; - args = StartApplication(menuSelectionProvider, args); + Work(menuSelectionProvider, false, false, true); } private void OnClickExportOverwriteSilent(MenuSelectionProvider menuSelectionProvider) { #if DEBUG Debugger.Launch(); #endif - string args = "export --overwrite --silent"; - args = StartApplication(menuSelectionProvider, args); + Work(menuSelectionProvider, false, true, true); } private void OnClickExport(MenuSelectionProvider menuSelectionProvider) { #if DEBUG Debugger.Launch(); #endif - string args = "export"; - args = StartApplication(menuSelectionProvider, args); + Work(menuSelectionProvider, false); } private void OnClickExportOverwrite(MenuSelectionProvider menuSelectionProvider) { #if DEBUG Debugger.Launch(); #endif - string args = "export --overwrite"; - args = StartApplication(menuSelectionProvider, args); + Work(menuSelectionProvider, false, true); } private void OnClickImport(MenuSelectionProvider menuSelectionProvider) @@ -69,72 +66,147 @@ private void OnClickImport(MenuSelectionProvider menuSelecti #if DEBUG Debugger.Launch(); #endif - string args = "import"; - args = StartApplication(menuSelectionProvider, args); + Work(menuSelectionProvider, true); } - private string StartApplication(MenuSelectionProvider menuSelectionProvider, string args) + private void Work(MenuSelectionProvider menuSelectionProvider, bool isImport, bool overwrite = false, bool silent = false) { - string fileDirectory = _tiaPortal.Projects.FirstOrDefault()?.Path.DirectoryName + "\\UserFiles\\"; - var currentProcess = _tiaPortal.GetCurrentProcess(); - string exePath = WriteApplicationToTempFolder(exeName); - args += " -t \""; - List deviceNames = new List(); - foreach (Device device in menuSelectionProvider.GetSelection()) + var tiaPortalProject = _tiaPortal.Projects.FirstOrDefault(); + using (var exclusiveAccess = _tiaPortal.ExclusiveAccess("ShowScripts Addin V19.22.0 starting...")) { - foreach (DeviceItem deviceItem in device.DeviceItems) + foreach (Device device in menuSelectionProvider.GetSelection()) { - SoftwareContainer softwareContainer = deviceItem.GetService(); - if (softwareContainer != null && softwareContainer.Software is HmiSoftware) // HmiSoftware means Unified + foreach (DeviceItem deviceItem in device.DeviceItems) { - deviceNames.Add(device.Name); + SoftwareContainer softwareContainer = deviceItem.GetService(); + if (softwareContainer != null && softwareContainer.Software is HmiSoftware) // HmiSoftware means Unified + { + string deviceName = device.Name; + var screens = GetScreens(tiaPortalProject, deviceName); + if (screens == null) + { + MessageBox.Show(@"Cannot find any HMI with name: " + deviceName + @" + If the device exists, but this error occurs, this is a known bug in TIA Portal. Workaround: Copy the HMI and connected PLC to a new created TIA Portal project and run the tool again. + Click to close and continue..."); + continue; + } + + string fileDirectory = tiaPortalProject.Path.DirectoryName + "\\UserFiles\\ShowScripts_" + deviceName + "\\"; + if (!Directory.Exists(fileDirectory)) + { + Directory.CreateDirectory(fileDirectory); + } + // Console.WriteLine("ShowScripts path: " + fileDirectory); + + var worker = new AddScriptsToList(fileDirectory, exclusiveAccess, deviceName); + if (!isImport) + { + worker.ExportScripts(screens, overwrite, silent, false); + + // run command to fix scripts with eslint rules + var processStartInfo = new ProcessStartInfo(); + processStartInfo.WorkingDirectory = fileDirectory; + processStartInfo.FileName = "cmd.exe"; + processStartInfo.Arguments = "/C npm run lint"; + Process proc = Process.Start(processStartInfo); + proc.WaitForExit(); + } + else + { + // import scripts + using (var transaction = exclusiveAccess.Transaction(tiaPortalProject, "Import scripts")) + { + worker.ImportScripts(screens); + } + // tiaPortalProject.Save(); + } + } } } } - args += string.Join(",", deviceNames) + "\""; - args += " -P " + "\"" + currentProcess.Id + "\""; - args += " -A " + "\"" + currentProcess.Path.ToString() + "\""; - - var process = Siemens.Engineering.AddIn.Utilities.Process.Start(exePath, args); - - return args; } - - - private string WriteApplicationToTempFolder(string exeResource, string[] referenceResources = null) + private static IEnumerable GetScreens(Project tiaProject, string deviceName) { - string tempDirectory = GetTemporaryDirectory(); - - File.WriteAllBytes(Path.Combine(tempDirectory, GetFileNameFromResource(exeResource)), GetResourceStream(exeResource)); - - if (referenceResources != null) + var screens = GetScreens(tiaProject.Devices, deviceName); + if (screens == null) + { + screens = GetScreens(tiaProject.DeviceGroups, deviceName); + } + return screens; + } + private static IEnumerable GetScreens(DeviceUserGroupComposition groups, string deviceName) + { + foreach (var group in groups) { - foreach (string resource in referenceResources) + var screens = GetScreens(group.Devices, deviceName); + if (screens != null) + { + return screens; + } + screens = GetScreens(group.Groups, deviceName); + if (screens != null) { - File.WriteAllBytes(Path.Combine(tempDirectory, GetFileNameFromResource(resource)), GetResourceStream(resource)); + return screens; } } + return null; + } - return Path.Combine(tempDirectory, GetFileNameFromResource(exeResource)); - } - private byte[] GetResourceStream(string name) + private static IEnumerable GetScreens(DeviceComposition devices, string deviceName) { - BinaryReader streamReader = new BinaryReader(this.GetType().Assembly.GetManifestResourceStream(name)); - - return streamReader.ReadBytes((int)streamReader.BaseStream.Length); + IEnumerable screens = null; + if (string.IsNullOrEmpty(deviceName)) + { + foreach (var device in devices) + { + screens = GetScreens(device); + if (screens != null) + { + deviceName = device.Name; + return screens; + } + } + } + else + { + var device = devices.FirstOrDefault(x => x.Name == deviceName); + if (device != null) + { + return GetScreens(device); + } + } + return null; } - private string GetTemporaryDirectory() + private static IEnumerable GetScreens(Device device) { - string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(tempDirectory); - return tempDirectory; + foreach (DeviceItem deviceItem in device.DeviceItems) + { + SoftwareContainer softwareContainer = deviceItem.GetService(); + if (softwareContainer != null && softwareContainer.Software is HmiSoftware) + { + var sw = (softwareContainer.Software as HmiSoftware); + var allScreens = sw.Screens.ToList(); + allScreens.AddRange(ParseGroups(sw.ScreenGroups)); + return allScreens; + } + } + return null; } - private string GetFileNameFromResource(string resourceName) - { - string resourceStart = "ShowScripts.OpennessExe."; - return resourceName.Substring(resourceStart.Length); + private static IEnumerable ParseGroups(HmiScreenGroupComposition parentGroups) + { + foreach (var group in parentGroups) + { + foreach (var screen in group.Screens) + { + yield return screen; + } + foreach (var screen in ParseGroups(group.Groups)) + { + yield return screen; + } + } } - + private MenuStatus DisplayStatus(MenuSelectionProvider menuSelectionProvider) { return MenuStatus.Enabled; diff --git a/OpennessConsoleApplication/AddScriptsToList.cs b/ShowScripts/AddScriptsToList.cs similarity index 85% rename from OpennessConsoleApplication/AddScriptsToList.cs rename to ShowScripts/AddScriptsToList.cs index 30e04cb..1271bc9 100644 --- a/OpennessConsoleApplication/AddScriptsToList.cs +++ b/ShowScripts/AddScriptsToList.cs @@ -31,9 +31,43 @@ class AddScriptsToList string globalDefinitionAreaScriptCodeEvents; List childScreens; int check = 0; - string delimiter = ";"; + private readonly string delimiter = ";"; + private readonly ExclusiveAccess exclusiveAccess; + private readonly string fileDirectory; + private readonly string logDirectory; + private readonly LinkedList rollingLog = new LinkedList(); + private readonly int MAX_ROLLING_LOG_LINES = 10; + private readonly string deviceName; + + public AddScriptsToList(string fileDirectory, ExclusiveAccess exclusiveAccess, string deviceName) + { + this.fileDirectory = fileDirectory; + this.logDirectory = fileDirectory + "Log.txt"; + this.exclusiveAccess = exclusiveAccess; + this.deviceName = deviceName; + Log(deviceName); + } + + private void Log(string text, bool noNewLine = false) + { + if (!noNewLine) + { + rollingLog.Append(text); + if (rollingLog.Count > MAX_ROLLING_LOG_LINES) + { + rollingLog.RemoveFirst(); + } + text += "\n"; + } + else + { + rollingLog.Last.Value += text; + } + File.AppendAllText(logDirectory, text); + this.exclusiveAccess.Text = string.Join("\n", rollingLog); + } - public void ImportScripts(IEnumerable screens, string fileDirectory) + public void ImportScripts(IEnumerable screens) { FileInfo[] Files = new DirectoryInfo(fileDirectory).GetFiles("*.js"); foreach (HmiScreen screen in screens) @@ -121,7 +155,7 @@ private void SetScriptFromFile(IHmiScript script, string[] lines, string eventNa } if (scriptLines.Count == 0) { - Console.WriteLine("Cannot find function with name " + functionName + " in script file."); + Log("Cannot find function with name " + functionName + " in script file."); return; } int lastBracketIndex = scriptLines.FindLastIndex(x => x.Trim() == "}"); @@ -133,7 +167,7 @@ private void SetScriptFromFile(IHmiScript script, string[] lines, string eventNa } else { - Console.WriteLine($"Did not change funtion {functionName}, because the script code is equal"); + Log($"Did not change funtion {functionName}, because the script code is equal"); } } @@ -147,14 +181,14 @@ private void SetScriptFromFile(IHmiScript script, string[] lines, string eventNa /// Case ignored, e.g. *, Screen_* /// e.g. Dynamization.Trigger.Type=250 /// e.g. Dynamization.Trigger.Type=4, Dynamization.Trigger.Tags='Refresh_tag' - public void ExportScripts(IEnumerable screens, string fileDirectory, string screenName, string deviceName, bool overwrite, bool silent, bool deepSearch = false) + public void ExportScripts(IEnumerable screens, bool overwrite, bool silent, bool deepSearch = false, bool versionLeadsToTextCrash = false) { string whereCondition = ""; string sets = ""; var csvStringP = new List(); - string _screenName = ""; + string screenName = ".*"; - if(!silent && screenName == ".*" && check == 0) + if(!silent && check == 0) { InputForm dialog = new InputForm(deviceName + " - Enter a screen name: "); dialog.Text = "Screen name"; @@ -163,7 +197,7 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, if (dialog.ShowDialog() == DialogResult.OK) { // Read the contents of testDialog's TextBox. - _screenName = dialog.ScreenName; + screenName = dialog.ScreenName; dialog.Dispose(); } else @@ -173,43 +207,36 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, } check = 1; } - else - { - _screenName = screenName; - } - - /*if (_screenName == "All screens") - { - screenName = ".*"; - } - else if (_screenName == "") - { - screenName = ""; - }*/ - if (_screenName != "" && _screenName != ".*" && screenName == ".*") - { - screenName = _screenName; - } - - using (StreamWriter sw = File.CreateText(fileDirectory + "TextboxesWithoutText.csv")) + string pathTextboxesWithoutText = fileDirectory + "TextboxesWithoutText.csv"; + using (StreamWriter sw = File.CreateText(pathTextboxesWithoutText)) { sw.WriteLine(string.Format("Screen{0}Object", delimiter)); } - using (StreamWriter sw = File.CreateText(fileDirectory + "ScreenItemsOutOfRange.csv")) + string pathScreenItemsOutOfRange = fileDirectory + "ScreenItemsOutOfRange.csv"; + using (StreamWriter sw = File.CreateText(pathScreenItemsOutOfRange)) { sw.WriteLine(string.Format("Screen{0}Object", delimiter)); } - using (StreamWriter sw = new StreamWriter(fileDirectory + "CyclicTrigger.csv")) + string pathCyclicTrigger = fileDirectory + "CyclicTrigger.csv"; + using (StreamWriter sw = new StreamWriter(pathCyclicTrigger)) { sw.WriteLine(string.Format("Screen{0}Object{0}Event/Dynamization{0}Cyclic trigger", delimiter)); } - using (StreamWriter sw = new StreamWriter(fileDirectory + "TagSetUsages.csv")) + Dictionary> tagSetUsages = new Dictionary>() + { + { ".SetTagValue(", new List() }, + { ".Read(", new List() }, + { ".Write(", new List() } + }; + string pathTagSetUsages = fileDirectory + "TagSetUsages.csv"; + using (StreamWriter sw = new StreamWriter(pathTagSetUsages)) { - sw.WriteLine(string.Format("Screen{0}Object{0}Event/Dynamization", delimiter)); + sw.WriteLine(string.Format("Screen{0}Object{0}Event/Dynamization{0}" + string.Join(delimiter, tagSetUsages.Keys.Select(x => x.Trim(new[] { '.', '(' }))), delimiter)); } - csvStringP.Add(string.Format("Screen name{0}Item count{0}Cycles{0}Disabled{0}Tags-Dyn-Scripts{0}Tags-Dyn{0} Total Number of Tags{0}Resource list{0}Events{0}Child screens{0}ScreenItemsOutOfRange{0}TextBoxesWithoutText{0}UseTagSet", delimiter)); + csvStringP.Add(string.Format("Screen name{0}Item count{0}Cycles{0}Disabled{0}Tags-Dyn-Scripts{0}Tags-Dyn{0} Total Number of Tags{0}Resource list{0}Events{0}Child screens{0}ScreenItemsOutOfRange{0}TextBoxesWithoutText{0}" + + string.Join(delimiter, tagSetUsages.Keys.Select(x => "TagSet_" + x.Trim(new[] { '.', '('}))), delimiter)); countScreenItems = new Dictionary() { @@ -260,7 +287,7 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, faceplateTypes = new Dictionary(); - var screensToExport = screens.Where(s => Regex.Matches(s.Name, _screenName, RegexOptions.IgnoreCase).Count > 0).ToList(); + var screensToExport = screens.Where(s => Regex.Matches(s.Name, screenName, RegexOptions.IgnoreCase).Count > 0).ToList(); var screenCount = screensToExport.Count; // if TIA Portal crashes, you can find out easily, which screen made the crash by checking which files were created and which is the next screen within this list. using (StreamWriter sw = new StreamWriter(fileDirectory + "ScreenNames.txt")) @@ -282,8 +309,8 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, var eveList = new List(); var screenDynEventList = new List(); // inits - Console.WriteLine(); - Console.Write("[" + (i + 1) + "/" + screenCount + "]" + screen.Name); + Log(""); + Log("[" + (i + 1) + "/" + screenCount + "]" + screen.Name, true); tagNames = new List(); List _dynamizationList = new List(); List _eveList = new List(); @@ -309,7 +336,11 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, var screenItemsOutOfRange = new List(); var cycles = new List(); var countTextboxesWithoutText = new List(); - IEnumerable tagSetUsages = new List(); + // reinit tag set usages + foreach (var key in tagSetUsages.Keys) + { + tagSetUsages[key].Clear(); + } foreach (var key in countScreenItems.Keys.ToList()) { @@ -322,20 +353,20 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, } // calculations - var screenDynsPropEves = GetAllMyAttributesDynPropEves(screen, deepSearch, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), ref tagSetUsages, ref cycles); + var screenDynsPropEves = GetAllMyAttributesDynPropEves(screen, deepSearch, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), tagSetUsages, ref cycles); var screenDyns = screenDynsPropEves[0]; var screenPropEves = screenDynsPropEves[1]; - var screenEves = GetAllMyAttributesEve(screen, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), ref tagSetUsages, ref cycles); + var screenEves = GetAllMyAttributesEve(screen, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), tagSetUsages, ref cycles); uint screenWidth = screen.Width; uint screenHeight = screen.Height; foreach (var screenitem in screen.ScreenItems) { - Console.Write('.'); // the user wants to see that something happens, so a dot will be printed for every screenitem - var screenitemDynsPropEves = GetAllMyAttributesDynPropEves(screenitem, deepSearch, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), ref tagSetUsages, ref cycles); + Log(".", true); // the user wants to see that something happens, so a dot will be printed for every screenitem + var screenitemDynsPropEves = GetAllMyAttributesDynPropEves(screenitem, deepSearch, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), tagSetUsages, ref cycles); var screenitemDyns = screenitemDynsPropEves[0]; var screenitemPropEves = screenitemDynsPropEves[1]; - var screenitemEves = GetAllMyAttributesEve(screenitem, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), ref tagSetUsages, ref cycles); + var screenitemEves = GetAllMyAttributesEve(screenitem, whereCondition.Split(',').ToList(), sets.Split(',').ToList(), tagSetUsages, ref cycles); screenItemEvents = screenItemEvents.Concat(screenitemEves).ToList().Concat(screenitemPropEves).ToList(); @@ -361,7 +392,7 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, } else { - Console.WriteLine("Screenitem Type: " + screenitem.GetType().Name + " is unknown."); + Log("Screenitem Type: " + screenitem.GetType().Name + " is unknown."); } if (!(screenitem is Siemens.Engineering.HmiUnified.UI.Shapes.HmiCentricShapeBase)) { @@ -375,7 +406,7 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, screenItemsOutOfRange.Add(screenitem.Name); } } - if (screenitem is HmiTextBox || screenitem is HmiText) + if (!versionLeadsToTextCrash && (screenitem is HmiTextBox || screenitem is HmiText)) { bool textboxWithoutText = true; foreach (var item in (screenitem.GetAttribute("Text") as MultilingualText).Items) // check if there is any character inside any text of any language @@ -444,7 +475,8 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, csvStringP.Add(string.Format(screen.Name + "{0}" + screen.ScreenItems.Count + "{0}" + (countDynTriggers["T100ms"] + countDynTriggers["T250ms"] + countDynTriggers["T500ms"] + countDynTriggers["T1s"] + countDynTriggers["T2s"] + countDynTriggers["T5s"] + countDynTriggers["T10s"] + countDynTriggers["OtherCycles"]) + "{0}" + countDynTriggers["Disabled"] + "{0}" + countDynTriggers["Tags"] + "{0}" + countDynTriggers["TagDynamizations"] + "{0}" + tagNames.Count() + "{0}" + countDynTriggers["ResourceLists"] + "{0}" + - eventListCount + "{0}" + string.Join("&", childScreens) + "{0}" + screenItemsOutOfRange.Count + "{0}" + countTextboxesWithoutText.Count + "{0}" + tagSetUsages.Count(), delimiter)); + eventListCount + "{0}" + string.Join("&", childScreens) + "{0}" + screenItemsOutOfRange.Count + "{0}" + countTextboxesWithoutText.Count + "{0}" + + string.Join(delimiter, tagSetUsages.Values.Select(x => x.Count)), delimiter)); foreach (var entry in countScreenItems) { @@ -473,7 +505,7 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, } if (countTextboxesWithoutText.Count() > 0) { - using (StreamWriter sw = new StreamWriter(fileDirectory + "TextboxesWithoutText.csv", true)) + using (StreamWriter sw = new StreamWriter(pathTextboxesWithoutText, true)) { foreach (var item in countTextboxesWithoutText) { @@ -481,21 +513,27 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, } } } - using (StreamWriter sw = new StreamWriter(fileDirectory + "ScreenItemsOutOfRange.csv", true)) + using (StreamWriter sw = new StreamWriter(pathScreenItemsOutOfRange, true)) { foreach (var item in screenItemsOutOfRange) { sw.WriteLine(screen.Name + delimiter + item); } } - using (StreamWriter sw = new StreamWriter(fileDirectory + "TagSetUsages.csv", true)) + using (StreamWriter sw = new StreamWriter(pathTagSetUsages, true)) { - foreach (var item in tagSetUsages) + int j = 0; + foreach (string key in tagSetUsages.Keys) { - sw.WriteLine(screen.Name + delimiter + item); + foreach (string item in tagSetUsages[key]) + { + // e.g. Screen_1;Loaded;;;1 + sw.WriteLine(screen.Name + delimiter + item + delimiter + new string(delimiter[0], j) + 1); + } + j++; } } - using (StreamWriter sw = new StreamWriter(fileDirectory + "CyclicTrigger.csv", true)) + using (StreamWriter sw = new StreamWriter(pathCyclicTrigger, true)) { foreach (var item in cycles) { @@ -534,8 +572,8 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, catch (Exception ex) { rtName = "Dummy_HMI_RT"; - Console.WriteLine("Failed to define the runtime name correctly, so use " + rtName + "Exception:"); - Console.WriteLine(ex); + Log("Failed to define the runtime name correctly, so use " + rtName + "Exception:"); + Log(ex.Message); } using (StreamWriter sw = new StreamWriter(fileDirectory + rtName + "_Scripts_Overview.csv")) @@ -543,49 +581,15 @@ public void ExportScripts(IEnumerable screens, string fileDirectory, sw.Write(string.Join(Environment.NewLine, csvStringP)); } - //check if files are filled or not and delete if they are not filled - int lineCount; - using (StreamReader sr = new StreamReader(fileDirectory + "CyclicTrigger.csv")) - { - lineCount = sr.ReadToEnd().Split('\n').Length; - } - if (lineCount <= 2) //2 because header and empty line afterwards - { - File.Delete(fileDirectory + "CyclicTrigger.csv"); - } - - lineCount = 0; - using (StreamReader sr = new StreamReader(fileDirectory + "ScreenItemsOutOfRange.csv")) - { - lineCount = sr.ReadToEnd().Split('\n').Length; - } - if (lineCount <= 2)//2 because header and empty line afterwards - { - File.Delete(fileDirectory + "ScreenItemsOutOfRange.csv"); - } - - lineCount = 0; - using (StreamReader sr = new StreamReader(fileDirectory + "TagSetUsages.csv")) - { - lineCount = sr.ReadToEnd().Split('\n').Length; - } - if (lineCount <= 2)//2 because header and empty line afterwards - { - File.Delete(fileDirectory + "TagSetUsages.csv"); - } - - lineCount = 0; - using (StreamReader sr = new StreamReader(fileDirectory + "TextboxesWithoutText.csv")) - { - lineCount = sr.ReadToEnd().Split('\n').Length; - } - if (lineCount <= 2)//2 because header and empty line afterwards + // remove empty files for clean up + foreach (var filePath in new List() { pathCyclicTrigger, pathScreenItemsOutOfRange, pathTagSetUsages, pathTextboxesWithoutText } + .Where(filePath => File.Exists(filePath) && File.ReadAllLines(filePath).Length <= 2)) //2 because header and empty line afterwards { - File.Delete(fileDirectory + "TextboxesWithoutText.csv"); + File.Delete(filePath); } } - public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, bool deepSearch, List whereConditions, List sets, ref IEnumerable tagSetUsage, ref List cycles) + public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, bool deepSearch, List whereConditions, List sets, Dictionary> tagSetUsage, ref List cycles) { var tempListDyn = new List(); var tempListPropEve = new List(); @@ -598,40 +602,40 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { if (itemsDyn.Value.Count == 2 && (obj is HmiScreen || obj is HmiScreenItemBase)) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListDyn.Insert(0, itemsDyn.Value[0]); string script = itemsDyn.Value[1]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsDyn.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsDyn.Key, tagSetUsage); tempListDyn.Insert(1, "function _" + objectName + "_" + itemsDyn.Key + "_Trigger() {" + script + Environment.NewLine + "}"); } if (itemsDyn.Value.Count == 1 && (obj is HmiScreen || obj is HmiScreenItemBase)) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListDyn.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); string script = itemsDyn.Value[0]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsDyn.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsDyn.Key, tagSetUsage); tempListDyn.Add("function _" + objectName + "_" + itemsDyn.Key + "_Trigger() {" + script + Environment.NewLine + "}"); } if (itemsDyn.Value.Count == 1 && !(obj is HmiScreen || obj is HmiScreenItemBase)) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListDyn.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); string script = itemsDyn.Value[0]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, itemsDyn.Key)); + SetTagSetUsage(script, itemsDyn.Key, tagSetUsage); tempListDyn.Add("_" + itemsDyn.Key + "_Trigger() {" + Environment.NewLine + script + Environment.NewLine + "}"); } } foreach (var itemsPropEve in propertyEvents) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script if (itemsPropEve.Value.Count == 2 && (obj is HmiScreen || obj is HmiScreenItemBase)) { tempListPropEve.Insert(0, itemsPropEve.Value[0]); string script = itemsPropEve.Value[1]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsPropEve.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsPropEve.Key, tagSetUsage); tempListPropEve.Insert(1, Environment.NewLine + "export function _" + objectName + "_" + itemsPropEve.Key + "_OnPropertyChanged() {" + script + Environment.NewLine + "}"); } @@ -639,7 +643,7 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { tempListPropEve.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); string script = itemsPropEve.Value[0]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsPropEve.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsPropEve.Key, tagSetUsage); tempListPropEve.Add("export function _" + objectName + "_" + itemsPropEve.Key + "_OnPropertyChanged() {" + script + Environment.NewLine + " }"); } @@ -647,7 +651,7 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { tempListPropEve.Insert(0, itemsPropEve.Value[0]); string script = itemsPropEve.Value[1]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, itemsPropEve.Key)); + SetTagSetUsage(script, itemsPropEve.Key, tagSetUsage); tempListPropEve.Insert(1, "_" + itemsPropEve.Key + "_OnPropertyChanged() {" + script + Environment.NewLine + "}"); } @@ -655,7 +659,7 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { tempListPropEve.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); string script = itemsPropEve.Value[0]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, itemsPropEve.Key)); + SetTagSetUsage(script, itemsPropEve.Key, tagSetUsage); tempListPropEve.Add("_" + itemsPropEve.Key + "_OnPropertyChanged() {" + script + Environment.NewLine + "}"); } } @@ -672,10 +676,10 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { if (item.GetType().Name != "MultilingualText") { - var nodeDynPropEve = GetAllMyAttributesDynPropEves(item, deepSearch, whereConditions, sets, ref tagSetUsage, ref cycles); + var nodeDynPropEve = GetAllMyAttributesDynPropEves(item, deepSearch, whereConditions, sets, tagSetUsage, ref cycles); foreach (var dyn in nodeDynPropEve[0]) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListDyn.Add("function _" + objectName + dyn); } int index = 0; @@ -683,12 +687,12 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, { if (index != 0) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListPropEve.Add(Environment.NewLine + "export function _" + obj.GetAttribute("Name") + propEve); } else { - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(propEve, obj.GetAttribute("Name").ToString())); + SetTagSetUsage(propEve, obj.GetAttribute("Name").ToString(), tagSetUsage); tempListPropEve.Add(propEve); index++; } @@ -699,11 +703,10 @@ public List> GetAllMyAttributesDynPropEves(IEngineeringObject obj, return new List>() { tempListDyn, tempListPropEve }; } - private List GetTagSetUsage(string script, string eventDynName) + private void SetTagSetUsage(string script, string eventDynName, Dictionary> tagSetUsage) { - var tagSetUsage = new List(); var scriptLines = script.Split('\n').Where(x => !string.IsNullOrWhiteSpace(x.Trim())); - var keyWordsToTest = new Dictionary { { ".Read(", 0 }, { ".Write(", 0 }, { ".SetTagValue(", 0 } }; + Dictionary keyWordsToTest = tagSetUsage.ToDictionary(x => x.Key, x => 0); var keys = keyWordsToTest.Keys.ToList(); foreach (var scriptLine in scriptLines) { @@ -713,15 +716,14 @@ private List GetTagSetUsage(string script, string eventDynName) keyWordsToTest[key]++; if (keyWordsToTest[key] >= 2) { - tagSetUsage.Add(eventDynName); + tagSetUsage[key].Add(eventDynName); } } } } - return tagSetUsage; } - public List GetAllMyAttributesEve(IEngineeringObject obj, List whereConditions, List sets, ref IEnumerable tagSetUsage, ref List cycles) + public List GetAllMyAttributesEve(IEngineeringObject obj, List whereConditions, List sets, Dictionary> tagSetUsage, ref List cycles) { List tempListEve = new List(); @@ -731,20 +733,20 @@ public List GetAllMyAttributesEve(IEngineeringObject obj, List w { if (itemsEve.Value.Count == 2) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script //tempListEve.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); tempListEve.Insert(0, itemsEve.Value[0]); string script = itemsEve.Value[1]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsEve.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsEve.Key, tagSetUsage); tempListEve.Insert(1, Environment.NewLine + "export async function _" + objectName + "_" + itemsEve.Key + "() {" + script + Environment.NewLine + "}"); } if (itemsEve.Value.Count == 1) { - Console.Write(';'); // the user wants to see that something happens, so a semicolon will be printed for every script + Log(";", true); // the user wants to see that something happens, so a semicolon will be printed for every script tempListEve.Add(Environment.NewLine + "//eslint-disable-next-line camelcase"); string script = itemsEve.Value[0]; - tagSetUsage = tagSetUsage.Concat(GetTagSetUsage(script, objectName + delimiter + itemsEve.Key)); + SetTagSetUsage(script, objectName + delimiter + itemsEve.Key, tagSetUsage); tempListEve.Add("export async function _" + objectName + "_" + itemsEve.Key + "() {" + script + Environment.NewLine + "}"); } } @@ -776,7 +778,7 @@ void SetMyAttributesSimpleTypes(string keyToSet, string valueToSet, IEngineering if (obj == null) { - Console.WriteLine("Language " + keyToSet + " does not exist in this Runtime!"); + Log("Language " + keyToSet + " does not exist in this Runtime!"); return; } keyToSet = "Text"; @@ -795,7 +797,7 @@ void SetMyAttributesSimpleTypes(string keyToSet, string valueToSet, IEngineering { obj.SetAttribute(keyToSet.ToString(), attrVal); } - catch (Exception ex) { Console.WriteLine(ex.Message); } + catch (Exception ex) { Log(ex.Message); } } private Dictionary> GetScripts(IEngineeringObject obj, string compositionName, List whereConditions, List sets, ref List cycles) @@ -941,14 +943,14 @@ private Dictionary> GetScripts(IEngineeringObject obj, stri } else { - Console.WriteLine("Unknown dynamization type: " + dyn.DynamizationType.ToString()); + Log("Unknown dynamization type: " + dyn.DynamizationType.ToString()); } dict.Add(dyn.PropertyName, listDyn); } } catch (Exception ex) { - Console.WriteLine(ex.Message); + Log(ex.Message); } } else // e.g. EventHandlers & PropertyEventHandlers diff --git a/ShowScripts/Debugconfig.xml b/ShowScripts/Debugconfig.xml index 770b90c..4e11adf 100644 --- a/ShowScripts/Debugconfig.xml +++ b/ShowScripts/Debugconfig.xml @@ -6,7 +6,7 @@ TIA Add-In ShowScripts - Debug version tia_add_in_show_scripts - 19.20.0 + 19.22.0 @@ -15,34 +15,15 @@ bin\Debug\ShowScripts.dll - + - - - - - - - - - - - - - - - - - - - - - - - - + + + Needed to speed up application. + + \ No newline at end of file diff --git a/OpennessConsoleApplication/InputForm.Designer.cs b/ShowScripts/InputForm.Designer.cs similarity index 100% rename from OpennessConsoleApplication/InputForm.Designer.cs rename to ShowScripts/InputForm.Designer.cs diff --git a/OpennessConsoleApplication/InputForm.cs b/ShowScripts/InputForm.cs similarity index 100% rename from OpennessConsoleApplication/InputForm.cs rename to ShowScripts/InputForm.cs diff --git a/OpennessConsoleApplication/InputForm.resx b/ShowScripts/InputForm.resx similarity index 100% rename from OpennessConsoleApplication/InputForm.resx rename to ShowScripts/InputForm.resx diff --git a/ShowScripts/Releaseconfig.xml b/ShowScripts/Releaseconfig.xml index ea51969..fe0cefc 100644 --- a/ShowScripts/Releaseconfig.xml +++ b/ShowScripts/Releaseconfig.xml @@ -6,7 +6,7 @@ TIA Add-In ShowScripts tia_add_in_show_scripts - 19.20.0 + 19.22.0 @@ -20,29 +20,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + Needed to speed up application. + + \ No newline at end of file diff --git a/ShowScripts/ShowScripts.csproj b/ShowScripts/ShowScripts.csproj index 11c0560..6757e11 100644 --- a/ShowScripts/ShowScripts.csproj +++ b/ShowScripts/ShowScripts.csproj @@ -43,6 +43,7 @@ + @@ -53,6 +54,13 @@ + + + Form + + + InputForm.cs + @@ -60,6 +68,9 @@ + + InputForm.cs +