Convert Part Units

Time to change teams

Have you ever needed to convert the units (inches to millimeters or vice versa) of the part you are working on? If so, you probably already know about the utility program, ug_convert_part.exe. For those not yet familiar, ug_convert_part.exe will convert the units of a single part, an entire assembly, or an entire directory of parts (with optional sub-directories), overwriting the originals or creating copies in a folder you specify. Suffice it to say that it has all of your part unit conversion needs covered. But... It is a command line interface (CLI) program. You'll have to type in all the commands you want it to execute, making sure to follow the syntax it expects. Did you make a typo in the argument list? At best, it will give you an error message and won't run; at worst, it will run with an option you didn't intend, possibly overwriting multiple files.

The graphical user interface (GUI) has spoiled us. Even seasoned users tend to be intimidated by CLI programs, especially those used infrequently. But with the power of some journal code, we can tame the CLI program to do our bidding while simultaneously making it user friendly.

The code below will use the utility ug_convert_part.exe to do what is perhaps the most common operation: convert the part units of a given part and overwrite the file. The code operates on the current work part (actually, it works best if the desired part is both the work and displayed part). As a precaution, a copy of the part will be placed in your temp directory (just in case).

The limitations of this version are:

  • only works on a piece part - if the part has one or more components, a message will display and the journal will exit.
  • only works on the native NX filesystem. It will not work with Teamcenter or other PDM/PLM system that stores your files in a database. If Teamcenter is detected, a warning message will appear and the journal will exit.


'NXJournaling.com
'May 13, 2013
'
'journal to convert the units of the work part, native NX filesystem only
'journal closes the work part and calls ug_convert_part, reports success/failure, and reopens the part
'
'changelog:
' June 5, 2013 - bugfix: target units assigned incorrectly

Option Strict Off
Imports System
Imports System.Diagnostics
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies

Module Module1

Sub Main()

Dim theSession As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession
Dim theUISession As UI = UI.GetUI
Dim workPart As Part = theSession.Parts.Work
Dim partPath As String = workPart.FullPath
Dim partName As String = System.IO.Path.GetFileName(partPath)
Dim copyPart As String = System.IO.Path.Combine(System.IO.Path.GetTempPath, partName)

Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()

Dim IsTcEng As Boolean = False
ufs.UF.IsUgmanagerActive(IsTcEng)
If IsTcEng Then
theUISession.NXMessageBox.Show("Native NX only", NXMessageBox.DialogType.Information, "This journal only works in native NX")
Exit Sub
End If

'lw.WriteLine("user: " & Environment.UserName)
'lw.WriteLine("part path: " & partPath)
lw.WriteLine("part name: " & partName)
'lw.WriteLine("copy destination: " & copyPart)
lw.WriteLine("current part units: " & workPart.PartUnits.ToString)

Dim targetUnits As String = ""
Dim unitArg As String = ""
If workPart.PartUnits = BasePart.Units.Millimeters Then
targetUnits = "inch"
unitArg = " -in "
Else
targetUnits = "metric"
unitArg = " -mm "
End If

Dim rm As RemoteUtilities = RemoteUtilities.GetRemoteUtilities()
Dim convertPath As String = rm.GetEnvironmentVariable("UGII_ROOT_DIR") & "ug_convert_part.exe"
'lw.WriteLine("UGII_ROOT_DIR: " & convertPath)

Dim c As ComponentAssembly = workPart.ComponentAssembly
If Not IsNothing(c.RootComponent) Then
lw.WriteLine("Assemblies not supported in this version, journal exiting")
Return
Else
lw.WriteLine("Part has no components, units will be converted")
End If

Dim response As Integer
response = theUISession.NXMessageBox.Show("Convert Units?", NXMessageBox.DialogType.Question, "Convert part to " & targetUnits & " units?")
'1 = Yes
'2 = No

If response = 2 Then
Return
End If

If ufs.Part.IsModified(workPart.Tag) Then
response = theUISession.NXMessageBox.Show("Save?", NXMessageBox.DialogType.Question, "Save part before closing?")

If response = 1 Then
'save and close
Dim partSaveStatus1 As PartSaveStatus
partSaveStatus1 = workPart.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.False)
partSaveStatus1.Dispose()
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing

Else
'just close
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Close Part")
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing
'UF_UNDO_delete_all_marks
End If

Else
'just close
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Close Part")
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing
'UF_UNDO_delete_all_marks
End If

'save backup copy to temp folder before conversion
Dim tempPath As String = System.IO.Path.GetTempPath
My.Computer.FileSystem.CopyFile(partPath, copyPart, True)

'tell user about backup copy
theUISession.NXMessageBox.Show("Backup Created", NXMessageBox.DialogType.Information, "A backup file has been saved to: " & copyPart)

Dim conversionSuccess As Boolean = False

Try

Dim convertProcess As New Process

Dim myStartInfo As New ProcessStartInfo
myStartInfo.UseShellExecute = False
myStartInfo.CreateNoWindow = True
myStartInfo.FileName = """" & convertPath & """" & unitArg & """" & partPath & """"
myStartInfo.RedirectStandardOutput = True
myStartInfo.RedirectStandardError = True

convertProcess.StartInfo = myStartInfo
convertProcess.Start()

Dim std_out As IO.StreamReader = convertProcess.StandardOutput()
Dim std_err As IO.StreamReader = convertProcess.StandardError()

Dim stdOutput As String = std_out.ReadToEnd
Dim stdLines() As String = stdOutput.Split(ControlChars.CrLf)

For Each Line As String In stdLines
If Line.ToUpper.Contains("SUCCESS") Then
conversionSuccess = True
End If
'lw.WriteLine(Line)
Next

Dim stdError As String = std_err.ReadToEnd
If Not String.IsNullOrEmpty(stdError) Then
lw.WriteLine("")
lw.WriteLine("stdErr:")
For Each Line As String In stdError
lw.WriteLine(Line)
Next
End If

std_out.Close()
std_err.Close()
convertProcess.Close()

Catch ex As Exception

lw.WriteLine("Error with ug_convert_part.exe")
lw.WriteLine(ex.GetType.ToString & " : " & ex.Message)

End Try

If conversionSuccess Then
theUISession.NXMessageBox.Show("Success", NXMessageBox.DialogType.Information, "File converted successfully, reopening file")
Else
theUISession.NXMessageBox.Show("Failure", NXMessageBox.DialogType.Information, "File failed to convert, reopening file")
End If

Dim basePart1 As BasePart
Dim partLoadStatus1 As PartLoadStatus
basePart1 = theSession.Parts.OpenBaseDisplay(partPath, partLoadStatus1)

workPart = theSession.Parts.Work
partLoadStatus1.Dispose()

End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

Conclusion

You can create a custom menu item and/or toolbar button to give your users one click access to part conversion. Or, if you need to convert entire assemblies or directories of parts, use the code as a guide and add in your desired options.

Happy coding!

Comments

I found and fixed a bug today. The target units were being assigned incorrectly (the journal would have tried to convert a metric part to metric units instead of inch units). If you have downloaded the previous code, please delete it and download this updated journal.

This code no longer works in NX 11.0

I get this error message;

Part name: BC14_BC-14.step_2017-01-10_HG.prt
Current part units: Millimeters
Part has no components, units will be converted
Error with ug_convert_part.exe
System.ComponentModel.Win32Exception: The specified file could not be found (The specified file can not be found)

I believe the error occurs on line 114 and the following

I thought the error could come from framemework, so I installed the 4.6.1 framework and the error still occurs.

You can help me ?

Sorry for my English, I'm French

Patrick

Pat

I do not have NX 11 fully up and running (yet), but I have heard that they moved many of the utilities into a subfolder named "NXBIN". The easy way to get this journal working again would be to find the "ug_convert_part.exe" file in the NX 11 install directory then change the following line of code to point to the new location.

change this:

Dim convertPath As String = rm.GetEnvironmentVariable("UGII_ROOT_DIR") & "ug_convert_part.exe"

to point to your NX 11 location; something like:

Dim convertPath As String = "C:\Program Files\Siemens\NX 11.0\NXBIN\ug_convert_part.exe"

I'll post updated code when I get NX 11 installed and running.

This completely slipped my mind; thanks to DaveK for the reminder.

'NXJournaling.com
'May 13, 2013
'
'journal to convert the units of the work part, native NX filesystem only
'journal closes the work part and calls ug_convert_part, reports success/failure, and reopens the part

'October 23, 2019
'updated to work with NX 11 and above:
'ug_convert_part is now located in the NXBIN folder
'removed call to remote utilities .GetEnvironmentVariable (obsolete)

Option Strict Off
Imports System
Imports System.Diagnostics
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies

Module Module2

Sub Main()

Dim theSession As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession
Dim theUISession As UI = UI.GetUI
Dim workPart As Part = theSession.Parts.Work
Dim partPath As String = workPart.FullPath
Dim partName As String = System.IO.Path.GetFileName(partPath)
Dim copyPart As String = System.IO.Path.Combine(System.IO.Path.GetTempPath, partName)
Const nxjID As String = "12a8872f-0d54-4c56-96b0-4449c512d92d"
theSession.LogFile.WriteLine("NXJID: " & nxjID)

Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()

Dim IsTcEng As Boolean = False
ufs.UF.IsUgmanagerActive(IsTcEng)
If IsTcEng Then
theUISession.NXMessageBox.Show("Native NX only", NXMessageBox.DialogType.Information, "This journal only works in native NX")
Exit Sub
End If

'lw.WriteLine("user: " & Environment.UserName)
'lw.WriteLine("part path: " & partPath)
'lw.WriteLine("part name: " & partName)
'lw.WriteLine("copy destination: " & copyPart)
'lw.WriteLine("current part units: " & workPart.PartUnits.ToString)

Dim targetUnits As String = ""
Dim unitArg As String = ""
If workPart.PartUnits = BasePart.Units.Millimeters Then
targetUnits = "inch"
unitArg = " -in "
Else
targetUnits = "metric"
unitArg = " -mm "
End If

Dim convertPath As String = theSession.GetEnvironmentVariableValue("UGII_BASE_DIR") & "\NXBIN\ug_convert_part.exe"
'lw.WriteLine("UGII_BASE_DIR: " & convertPath)

Dim c As ComponentAssembly = workPart.ComponentAssembly
If Not IsNothing(c.RootComponent) Then
lw.WriteLine("Assemblies not supported in this version, journal exiting")
Return
Else
lw.WriteLine("Part has no components, units will be converted")
End If

Dim response As Integer
response = theUISession.NXMessageBox.Show("Convert Units?", NXMessageBox.DialogType.Question, "Convert part to " & targetUnits & " units?")
'1 = Yes
'2 = No

If response = 2 Then
Return
End If

If ufs.Part.IsModified(workPart.Tag) Then
response = theUISession.NXMessageBox.Show("Save?", NXMessageBox.DialogType.Question, "Save part before closing?")

If response = 1 Then
'save and close
Dim partSaveStatus1 As PartSaveStatus
partSaveStatus1 = workPart.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.False)
partSaveStatus1.Dispose()
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing

Else
'just close
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Close Part")
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing
'UF_UNDO_delete_all_marks
End If

Else
'just close
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Close Part")
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
workPart = Nothing
'UF_UNDO_delete_all_marks
End If

'save backup copy to temp folder before conversion
Dim tempPath As String = System.IO.Path.GetTempPath
My.Computer.FileSystem.CopyFile(partPath, copyPart, True)

'tell user about backup copy
theUISession.NXMessageBox.Show("Backup Created", NXMessageBox.DialogType.Information, "A backup file has been saved to: " & copyPart)

Dim conversionSuccess As Boolean = False

Try

Dim convertProcess As New Process

Dim myStartInfo As New ProcessStartInfo
myStartInfo.UseShellExecute = False
myStartInfo.CreateNoWindow = True
myStartInfo.FileName = """" & convertPath & """" & unitArg & """" & partPath & """"
myStartInfo.RedirectStandardOutput = True
myStartInfo.RedirectStandardError = True

'lw.WriteLine("""" & convertPath & """" & unitArg & """" & partPath & """")
convertProcess.StartInfo = myStartInfo
convertProcess.Start()

Dim std_out As IO.StreamReader = convertProcess.StandardOutput()
Dim std_err As IO.StreamReader = convertProcess.StandardError()

'lw.WriteLine("")
'lw.WriteLine("stdout:")

Dim stdOutput As String = std_out.ReadToEnd
Dim stdLines() As String = stdOutput.Split(ControlChars.CrLf)

For Each Line As String In stdLines
If Line.ToUpper.Contains("SUCCESS") Then
conversionSuccess = True
End If
'lw.WriteLine(Line)
Next

Dim stdError As String = std_err.ReadToEnd
If Not String.IsNullOrEmpty(stdError) Then
lw.WriteLine("")
lw.WriteLine("stdErr:")
For Each Line As String In stdError
lw.WriteLine(Line)
Next
End If

std_out.Close()
std_err.Close()
convertProcess.Close()

Catch ex As Exception

lw.WriteLine("Error with ug_convert_part.exe")
lw.WriteLine(ex.GetType.ToString & " : " & ex.Message)

End Try

If conversionSuccess Then
theUISession.NXMessageBox.Show("Success", NXMessageBox.DialogType.Information, "File converted successfully, reopening file")
Else
theUISession.NXMessageBox.Show("Failure", NXMessageBox.DialogType.Information, "File failed to convert, reopening file")
End If

Dim basePart1 As BasePart
Dim partLoadStatus1 As PartLoadStatus
basePart1 = theSession.Parts.OpenBaseDisplay(partPath, partLoadStatus1)

workPart = theSession.Parts.Work
partLoadStatus1.Dispose()

End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer

GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately

End Function

End Module

Thanks for your help, it works!

Has anyone made a code to convert a complete assembly? It would be super useful !!!

Pat

If you are a member of the Siemens community site, the following thread has some utilities (near the end of the thread) that make using "ug_convert_part" easier.

https://community.plm.automation.siemens.com/t5/NX-Design-Forum/Easier-u...

I'm looking for a command (.exe) that I can use to know what is the measurement unit of an nx (.prt) component...a command like ug_inspect.exe. I want to know from the Windows explorer if a component is IN or MM without starting NX.

I want to add a key in the registry (REGEDIT) to add a shortcut in my right button menu when I click on a .prt file in Windows explorer.

Example similar to what I want to do (NX11.0 not NX10.0);

******************************************************************
reg.exe add "HKEY_CLASSES_ROOT\UGpartfile\shell\NX Part Version\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_inspect.exe\" -release \"%%1\" ^& pause \" " /f

REG ADD "HKCR\UGpartfile\shell\NX Convert to mm\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_convert_part.exe\" -mm \"%%1\" ^& pause \" " /f

REG ADD "HKCR\UGpartfile\shell\NX Convert to Inches\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_convert_part.exe\" -in \"%%1\" ^& pause \" " /f
******************************************************************

But, this command should be able to be used from the command prompt of nx (DOS).

Pat

Below is a VBScript that uses ug_inspect to find the units of the specified part file. You should be able to adapt it to your needs. I tested it with NX 9; it does not reference the "NXBIN" folder. Copy & paste the code into a plain text file and name it with the extension ".vbs". You can call the script from the command line {script name}.vbs "path to your part file", or drag & drop a part file onto the script file to process it (report the units in a message box).

'NX part file version

Set objFSO = CreateObject("Scripting.FileSystemObject")

If Not objFSO.FileExists(WScript.Arguments(0)) Then
wscript.echo("Invalid file")
wscript.quit
End If

Set objShell = CreateObject( "WScript.Shell" )
Set objEnv = objShell.Environment("Process")

strProgramPath = objEnv("UGII_ROOT_DIR") & "ug_inspect.exe"

Set objWshScriptExec = objShell.Exec(strProgramPath & " " & chr(34) & WScript.Arguments(0) & chr(34))

lineTest = "Part units: "
'create object to catch external program's output
Set objStdOut = objWshScriptExec.StdOut
Do While Not objStdOut.AtEndOfStream
strLineTest = objStdOut.ReadLine
pos = instr(strLineTest, lineTest)
if pos > 0 then
units = Right(strLineTest, Len(strLineTest) - Len(lineTest))
end if
Loop
wscript.echo("units: " & units)

To add commands to the right mouse button for windows explorer ... You dont need to start nx to use these commands !!!

Procedure.....

First;
Create a "AddToRightClicMenu.bat" file, that will add to the Windows registry database the information needed to add commands to the right mouse button from windows explorer for a .prt file only.
- Convert part Inches to Metric.
- Convert part Metric to Inches.
- Infos Units (Inches or Metric).
- NX version... In which version of nx the file was saved.

In the "AddToRightClicMenu.bat" file, you will need to adjust the "Info_Units.vbs" path... for me it's (C:\Temp_NX\SettingNX\NX11.0\Start_NX11.0\Info_Units.vbs\).

You need to adjust the following line code in "AddToRightClicMenu.bat"... adjust the path: REG ADD "HKCR\UGpartfile\shell\NX Info Units\command" /t reg_sz /d "cmd.exe /s/c \" @\"C:\Temp_NX\SettingNX\NX11.0\Start_NX11.0\Info_Units.vbs\" \"%%1\"

AddToRightClicMenu.bat ----------you need to create this file.... with the note pad ----------------------------------
@echo off
:: (c) 2017 Patrick
::
:: Ce script ajoute des commandes de conversion de fichiers NX dans le menu contextuel ainsi
:: que la version de NX installé et les informations d'un assemblage.
::
setlocal ENABLEDELAYEDEXPANSION
echo;
echo Ajout de la commande "NX Assy Info"
echo;
REG ADD "HKEY_CLASSES_ROOT\UGpartfile\shell\NX Assy Info\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ugpc.exe\" -s -a \"%%1\" ^& pause \" " /f
echo;
echo Ajout de la commande "NX Version"
echo;
REG ADD "HKEY_CLASSES_ROOT\UGpartfile\shell\NX Part Version\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_inspect.exe\" -release \"%%1\" ^& pause \" " /f
echo;
echo Ajout de la commande "NX Convert Units - Metric"
echo;
REG ADD "HKCR\UGpartfile\shell\NX Convert to Metric\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_convert_part.exe\" -mm \"%%1\" ^& pause \" " /f
echo;
echo Ajout de la commande "NX Convert Units - Inches"
echo;
REG ADD "HKCR\UGpartfile\shell\NX Convert to Inches\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_convert_part.exe\" -in \"%%1\" ^& pause \" " /f
echo;
echo Ajout d'un racoucci de pour connaitre si une composante NX est corrompu
echo;
REG ADD "HKCR\UGpartfile\shell\NX Corrupted Part\command" /t reg_sz /d "cmd.exe /s/c \" @\"%UGII_BASE_DIR%\nxbin\ug_inspect.exe\" -scan \"%%1\" ^& pause \" " /f
echo;
echo Ajout d'un racoucci pour connaitre l'unitee de mesure d'une composante NX
echo;
REG ADD "HKCR\UGpartfile\shell\NX Info Units\command" /t reg_sz /d "cmd.exe /s/c \" @\"C:\Temp_NX\SettingNX\NX11.0\Start_NX11.0\Info_Units.vbs\" \"%%1\"
echo;
:EOF
pause
---------------------------------------------------------------------------------------------------

Secondly;
Create a "Info_Units.vbs" file that you will save to your computer.

In the Info_Units.vbs file, you will need to adjust the following line to specify where is saved "ug_inspect.exe"... for me it's(C:\Siemens\NX11.0\NXBIN\ug_inspect.exe)
In NX10 and lower = ug_inspect.exe it's in UGII
In NX11 = ug_inspect.exe it's in NXBIN

You need to adjust the following line code in "Info_Units.vbs"... adjust the path: strProgramPath = "C:\Siemens\NX11.0\NXBIN\ug_inspect.exe"

Info_Units.vbs ----------you need to create this file.... with the note pad ----------------------------------
'NX part file version

Set objFSO = CreateObject("Scripting.FileSystemObject")

If Not objFSO.FileExists(WScript.Arguments(0)) Then
wscript.echo("Invalid file")
wscript.quit
End If

Set objShell = CreateObject( "WScript.Shell" )
Set objEnv = objShell.Environment("Process")

strProgramPath = "C:\Siemens\NX11.0\NXBIN\ug_inspect.exe"

Set objWshScriptExec = objShell.Exec(strProgramPath & " " & chr(34) & WScript.Arguments(0) & chr(34))

lineTest = "Part units: "
'create object to catch external program's output
Set objStdOut = objWshScriptExec.StdOut
Do While Not objStdOut.AtEndOfStream
strLineTest = objStdOut.ReadLine
pos = instr(strLineTest, lineTest)
if pos > 0 then
units = Right(strLineTest, Len(strLineTest) - Len(lineTest))
end if
Loop
wscript.echo ("Unité: " & units)
WScript.Quit
---------------------------------------------------------------------------------------------------

Enjoy !!!

Pat