Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisClems committed Mar 27, 2024
0 parents commit 3eeeead
Show file tree
Hide file tree
Showing 8 changed files with 453 additions and 0 deletions.
79 changes: 79 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.idea/

# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# SonarLint plugin
.idea/sonarlint/

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
10 changes: 10 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?><configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SharpShell" publicKeyToken="f14dc899472fe6fb" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Binary file added Key.snk
Binary file not shown.
89 changes: 89 additions & 0 deletions OpenTopLevelAsm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SharpShell.Attributes;
using SharpShell.SharpContextMenu;
using Application = SolidEdge.Framework.Interop.Application;

namespace SolidEdgeTopLevelAsmOpener
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.Directory)]
public class OpenTopLevelAsm : SharpContextMenu
{
private ContextMenuStrip menu = new ContextMenuStrip();

protected override bool CanShowMenu()
{
// Check that only one item is selected and that it is a directory
return SingleItem() && IsDirectory();
bool SingleItem() => SelectedItemPaths.Count() == 1;
bool IsDirectory() => File.GetAttributes(SelectedItemPaths.First()).HasFlag(FileAttributes.Directory);
}

protected override ContextMenuStrip CreateMenu()
{
// Mostly adapted from SharpShell example:
// https://www.codeproject.com/Articles/1035998/NET-Shell-Extensions-Adding-submenus-to-Shell-Cont
menu.Items.Clear();
// TODO: Find way in SharpShell to handle pre-existing dropdown and add to it.
ToolStripMenuItem SEMenu;
SEMenu = new ToolStripMenuItem
{
Text = "Solid Edge"
};

var openParentAssemblies = new ToolStripMenuItem
{
Text = "Open Top-Level Assemblies"
};
openParentAssemblies.Click += (sender, args) => openAsmFiles();
SEMenu.DropDownItems.Add(openParentAssemblies);
menu.Items.Clear();
menu.Items.Add(SEMenu);
return menu;
}

private void openAsmFiles()
{
// Check if any .asm files exist in selected path before launching SE.
var path = SelectedItemPaths.First();
var asmFiles = Directory.GetFiles(path, "*.asm");
Application SEApp = null;
if (asmFiles.Any())
{
// Find running SE instance or launch new one.
OleMessageFilter.Register();
if (SEAppHelper.SEIsRunningForeground(out SEApp))
{
SEApp.DoIdle();
}
else
{
SEApp = SEAppHelper.SEStart();
SEApp.DoIdle();
}
// !! Must initialize Array with new operator or will throw NullRefEx
Array topLevelAsms = new string[] { };
SEApp.GetListOfTopLevelAssembliesFromFolder(path, out topLevelAsms);
SEApp.DoIdle();
if (topLevelAsms != null)
{
foreach (string asm in topLevelAsms)
{
SEApp.Documents.Open(asm);
SEApp.DoIdle();
}
}
}

OleMessageFilter.Revoke();
if (SEApp != null)
{
Marshal.FinalReleaseComObject(SEApp);
}
}
}
}
35 changes: 35 additions & 0 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Reflection;
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("SolidEdgeTopLevelAsmOpener")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SolidEdgeTopLevelAsmOpener")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[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("7F74D2DB-698E-4DB4-ABF1-9758623AB32E")]

// 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")]
147 changes: 147 additions & 0 deletions SolidEdgeAppHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace SolidEdgeTopLevelAsmOpener
{
using SolidEdge.Framework.Interop;

#region OleMessageFilter

internal class OleMessageFilter : IOleMessageFilter
{
public static void Register()
{
IOleMessageFilter newFilter = new OleMessageFilter();
IOleMessageFilter oldFilter = null;

if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
CoRegisterMessageFilter(newFilter, out oldFilter);
else
throw new COMException(
"Unable to register message filter because the current thread apartment state is not STA.");
}

public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}

int IOleMessageFilter.HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo)
{
return (int)SERVERCALL.SERVERCALL_ISHANDLED;
}

int IOleMessageFilter.RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType)
{
if (dwRejectType == (int)SERVERCALL.SERVERCALL_RETRYLATER) return 99;

return -1;
}

int IOleMessageFilter.MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType)
{
return (int)PENDINGMSG.PENDINGMSG_WAITDEFPROCESS;
}

[DllImport("Ole32.dll")]
private static extern int CoRegisterMessageFilter(
IOleMessageFilter newFilter,
out IOleMessageFilter oldFilter);
}

internal enum SERVERCALL
{
SERVERCALL_ISHANDLED = 0,
SERVERCALL_REJECTED = 1,
SERVERCALL_RETRYLATER = 2
}

internal enum PENDINGMSG
{
PENDINGMSG_CANCELCALL = 0,
PENDINGMSG_WAITNOPROCESS = 1,
PENDINGMSG_WAITDEFPROCESS = 2
}

[ComImport()]
[Guid("00000016-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);

[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);

[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}

#endregion

public static class SEAppHelper
{
internal static bool SEIsRunningForeground(out Application SEApp)
{
try
{
SEApp = (Application)Marshal.GetActiveObject("SolidEdge.Application");
SEApp.DisplayAlerts = true;
SEApp.ResumeMRU();
SEApp.DelayCompute = false;
SEApp.Interactive = true;
SEApp.ScreenUpdating = true;
SEApp.Visible = true;
return true;
}
catch (Exception)
{
SEApp = null;
return false;
}
}

internal static Application SEStart()
{
try
{
var appType = Type.GetTypeFromProgID("SolidEdge.Application");
var SEApp = (Application)Activator.CreateInstance(appType);
SEApp.DisplayAlerts = true;
SEApp.ResumeMRU();
SEApp.DelayCompute = false;
SEApp.Interactive = true;
SEApp.ScreenUpdating = true;
SEApp.Visible = true;
return SEApp;
}
catch (Exception)
{
return null;
}
}
}
}
Loading

0 comments on commit 3eeeead

Please sign in to comment.