3 Replies Latest reply on Aug 2, 2017 7:51 AM by Alexander Schaaf

    Changing configurations in nested assembly

    Jana Fischer

      I have a nested assembly:

      nestedAssembly.png

       

      All components have two configurations. I want to change all configurations via API.

       

      For the root component I can use IModelDoc2.ShowConfiguration2(<name>).

      For the first layer, i.e. part1 and assy1, it works with IComponent2.ReferencedConfiguration = <name>.

       

      But IComponent2.ReferencedConfiguration does not work for the lower layers (i.e. part2, assy2, part3, assy3). You can try this yourself if you like.

      Here is the code in C#:

       

              public void ToggleAllConfigsDoesntWork()

              {

                  IModelDoc2 doc = _swApp.ActiveDoc;      // _swApp is the ISldWorks object

       

                  string activeConf = doc.ConfigurationManager.ActiveConfiguration.Name;

                  Debug.WriteLine("    active configuration: " + activeConf);

                  string[] configNames = doc.GetConfigurationNames();

       

                  string newConfig = null;

                  foreach (string configName in configNames)   // find a non-active configuration of root...

                      if (configName != activeConf)

                      {

                          newConfig = configName;

                          break;

                      }

       

                  Debug.WriteLine("    target configuration: " + newConfig);

                  doc.ShowConfiguration2(newConfig);   // ... and switch to that configuration.

                  Debug.WriteLine("    new configuration: " + doc.ConfigurationManager.ActiveConfiguration.Name);

       

       

       

                  object[] children = activeDoc.GetComponents(false);  // get all child components

                  string[] newConfigNames = new string[children.Length];

       

                  for (int i = 0; i < children.Length; i++)   // find non-active configurations for all children...

                  {

                      IComponent2 child = children[i] as IComponent2;

                      IModelDoc2 childDoc = child.GetModelDoc2();

                      string[] configNames = childDoc.GetConfigurationNames();

       

                      foreach (string configName in configNames)

                          if (configName != child.ReferencedConfiguration)

                          {

                              newConfigNames[i] = configName;

                              break;

                          }

                  }

       

                  for (int i = 0; i < children.Length; i++)   // ...and switch to these configurations.

                  {

                      IComponent2 child = children[i] as IComponent2;

       

                      Debug.WriteLine("component name: " + child.Name2);

                      Debug.WriteLine("    active configuration: " + child.ReferencedConfiguration);

                      Debug.WriteLine("    target configuration: " + newConfigNames[i]);

                      child.ReferencedConfiguration = newConfigNames[i];

       

                      Debug.WriteLine("    new configuration: " + child.ReferencedConfiguration);

                  }

       

                  bool success = doc.EditRebuild3();

              }

       

      You can use the attached assembly for testing. In the debug output you can see that the active configurations are correctly determined, and the target configurations as well. But changing the configuration just doesn't have any effect!

       

      Any hints on how I can make it work?

       

       

      I already noticed that using the method IAssemblyDoc.CompConfigProperties4 DOES work for all levels (except the root one). However, this is a method where things need to be selected in order to call it, and I have performance issues (selection is slow!). I want to avoid selecting if possible.

        • Re: Changing configurations in nested assembly
          Nilesh Patel

          Hi Jana,

           

          I believe IComponent2.ReferencedConfiguration only works for top level components not for child or lower level components. You probably will have to go with selection option.

           

          Regards,

          • Re: Changing configurations in nested assembly
            Jana Fischer

            I found a way to change configurations without selecting anything:

             

            The key is the method "IConfigurationManager.SetConfigurationParams".

            To change the configuration of a component B, we need to get its parent component A and call

             

            A.GetModelDoc2().ConfigurationManager.SetConfigurationParams(activeConfA, paramKeys, paramValues)

             

            where

            activeConfA = A.ReferencedConfiguration;

            paramKeys = new string[] {"$configuration@" + nameB};

            paramValues = new string[] {targetConfigB};

             

            nameB is the name of component B as seen in the feature tree, like "part2<1>". This can be retrieved by taking B.Name2 and processing this string a bit (split by "\", take last item after split, replace the last occurrence of "-" by "<", add ">" to the end).

             

            targetConfigB is the name of the configuration we want to activate for component B.

             

            It is also possible to change the configurations of several components as long as they have the same parent. In this case, paramKeys and paramValues have several entries and all entries follow the above schema.

            • Re: Changing configurations in nested assembly
              Alexander Schaaf

              Hello,

              I know this thread is old, but I didn't like the both solutions, so I started another approach and It's working like a charm without any string operations:

              Protected Iterator Function TraverseComponents(__Component2 As Component2) As IEnumerable(Of Component2)
              Dim swChildComponents As Object() = DirectCast(__Component2.GetChildren, Object())
              
              For Each swChildComponent As Component2 In swChildComponents
              
              
              Select Case System.IO.Path.GetExtension(swChildComponent.GetPathName)
              
              Case ".SLDASM"
              Dim swAssemblyDoc As ModelDoc2 = swChildComponent.IGetModelDoc
              If swAssemblyDoc IsNot Nothing Then
              Dim __swConfiguration As Configuration = swAssemblyDoc.IGetConfigurationByName(swChildComponent.ReferencedConfiguration)
              Dim __swRootComponent As Component2 = __swConfiguration.GetRootComponent3(True)
              
              If __swRootComponent.IsRoot Then
              For Each __Component In TraverseComponents(__swRootComponent)
              Yield __Component
              Next
              End If
              End If
              
              End Select
              
              Yield swChildComponent
              
              Next
              End Function
              

              So I just reinitialize the component root for every traversed assembly. This allows me to access the Component.ReferencedConfiguration.

              Use this function like:

              Dim __swConfiguration As Configuration = swAssemblyDoc.IGetConfigurationByName(StrActiveConfig)
              Dim __swRootComponent As Component2 = __swConfiguration.GetRootComponent3(True)
              
              If __swRootComponent.IsRoot Then
              
              For Each __Component In TraverseComponents(__swRootComponent)
              DO YOUR STUFF HERE
              Next
              End If
              

              Hope anyone still finds it useful.